Advanced GIT — Merge, History & Diffs

0_FTv5usi0zKtQTP0F.jpg

Merge seems to be a very simple topic, but it on first glance. We’ll learn what’s difference between ^ and ~ in GIT and uncover the full potential of the GIT log. This article continuous series of “Advanced GIT”. We’ve already talked about References, Git code store areas and what’s git. Let’s continue our journey 🏇.

Merge commits are just commits

                > git cat-file -p 5b5200bcd
tree 6f7df6413905f826d34d03db65db07ac44534835
parent f217ba90579095b77f463667538beb3f28273926
parent f63976bc4f2baa1fcfb0c6868fe398c289efe0b3
author Kenneth Reitz <me@kennethreitz.org> 1499378257 -0400
committer Kenneth Reitz <me@kennethreitz.org> 1499378257 -0400
Merge branch 'master' of github.com:kennethreitz/requests
            

ℹ️: Make notice that this commit has 2 parents

1_3n8VhZ4UVjZ1obpyJdGHTw.png

Merge commit

Fast forward

                > git checkout master
> git merge feature
Updating 2733233..9703930
Fast-forward
index.txt | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
            

Fast forward occurs when there are no commits on the base branch after the feature branch was created.

1_tYxhi2vpD0h3RPhUPoytaw.png

fast forward commit

No fast forward

git merge --no-ff — will force a merge commit, even when one isn’t necessary

1_Yol2OdGdov_FvUl6-VH1vA.png

force merge commit

Merge conflicts

Merge conflicts occur when you try to merge, but files have significantly changed. GIT will wait until conflicts are resolved

                > git merge feature
Auto-merging feature
CONFLICT (add/add): Merge conflict in feature
            
1_IUpDtreMCbi2pSceVYBHPw.png

Merge conflict

GIT RERERE — Reuse Recorded Resolution

GIT can remember how you solved the previous merge conflict and in the next commit reuse the same resolution.

Useful for long-lived branches (like refactoring) or rebasing.

How to enable it:

  1. git config rerere.enabled true
  2. add --global flag to enable in all projects

Example:

                > git config rerere.enabled true
> git checkout master
> git merge feature
Auto-merging feature
CONFLICT (add/add): Merge conflict in file
Recorded preimage for 'file'
Automatic merge failed; fix conflicts and then commit the result.
### Fix the merge conflict in file.
❯ git add file
❯ git commit -m "Resolve conflict"
Recorded resolution for 'feature'.
[master aa7291a] Resolve conflict
            

When we’ve committed conflict resolution, GIT has recorded it.

Now, let’s undid merge and try again.

                > git merge feature
Auto-merging feature
CONFLICT (add/add): Merge conflict in feature
Resolved 'feature' using previous resolution.
Automatic merge failed; fix conflicts and then commit the result.
> git add file
> git diff --staged
diff --git a/file b/file
index 587be6b..a354eda 100644
--- a/file
+++ b/file
@@ -1 +1 @@
-The old change
+This is how I resolved my conflict.
\ No newline at end of file
            

The resolution is automatically applied.

History & Diffs

1_bLtPTIsKUeAQHPo2eGrKpw.png

XKCD Bad commits

Good commits are important

Informative commits help preserve the history of code

When they’re helpful:

  • debugging & troubleshooting
  • creating release notes
  • code reviews
  • rolling back
  • associating the code with an issue or ticket

Rules of a good commit message

  • commit message is in the future tense fix
  • Short subject followed by a blank line

                git-rebase: don't ignore unexpected command line arguments
Currently, git-rebase will silently ignore any unexpected command-line switches and arguments (the command-line produced by git rev-parse). This allowed the rev-parse bug, fixed in the preceding commits, to go unnoticed. Let's make sure that doesn't happen again. We shouldn't be ignoring unexpected arguments. Let's not.
            

A description of the current behaviour, and a summary of why the fix is needed. Don’t forget to warn of the side effects.

  • informative commit message
  • encapsulates one logical idea
  • Doesn’t introduce breaking changes (tests should pass)

GIT Log

git log — the basic command that shows you the history of your repository

                git log
commit 767c4fd32dbcff87f8e040156e1a95a59f4bf730 (HEAD -> master)
Author: d9nich <54186666+d9nchik@users.noreply.github.com>
Date:   Mon Aug 22 09:51:42 2022 +0300
initial commit
            

“Why my app is slow? It has been working since yesterday” — typical situation at the workplace

Typical usage:

  • git log --since="yesterday"
  • git log --since="2 weeks ago"
  • git log --name-status --follow -- <file> — log files that have been renamed or moved
  • git log --grep <regexp> — Search for commit messages that match a regular expression

ℹ️: You can combine different flags:

                > git log --grep=mail --author=bob --since=3.weeks
            

GIT log diff-filter

Selectively include or exclude files that have been:

  • A — added
  • D — deleted
  • M — modified
  • and more

                > git log --diff-filter=R --stat
5e1ced3 make session serializer extensible support serializing 1-item dicts
with tag as key refactor serializer into flask.json.tag module continues
#1452, closes #1438, closes #1908
flask/{json.py => json/__init__.py} | 13 ++-----------
1 file changed, 2 insertions(+), 11 deletions(-)
8cf32bc Adds in blueprints and an application factory
examples/flaskr/flaskr/{ => blueprints}/flaskr.py | 55 ++++++++++++++
+----------------------------------------
1 file changed, 15 insertions(+), 40 deletions(-)
92fa444 Moves largerapp into patterns dir and add test
examples/{ => patterns}/largerapp/setup.py
| 0
examples/{ => patterns}/largerapp/yourapplication/__init__.py
| 0
examples/{ => patterns}/largerapp/yourapplication/static/style.css
| 0
examples/{ => patterns}/largerapp/yourapplication/templates/index.html | 0
            

Referencing commits

^ or ^n :

  • ^= ^1 : the first parent commit
  • ^n : the n-th parent commit

~ or ~n :

  • ~ = ~1 : the first commit back, following 1st parent
  • ~n : number of commits back, following only 1st parent

ℹ️: ^ and ~ can be combined

1_15hK6JotkfPV8HKwLUP1Vw.png

commit reference example

Preface:

  • B and C are parents of node A
  • Parents are ordered left-right
  • A is the latest commit

Then we have the following equality:

                A       = A^0
B = A^  = A^1   = A~1
C = A^2
D = A^^ = A^1^1 = A~2
E = B^2 = A^^2
F = B^3 = A^^3  = A^2^1
            

GIT show — look at the commit

  • git show <commit> — show commit and contents
  • git show <commit> --stat — show file changed in the commit
  • git show <commit>:<file> — look at the file from the commit

Diff

shows you change between:

  • commits
  • staging area and repository
  • what’s in the working area

git diff — unstaged changes

git diff --staged — staged changes

1_UeLamqy84dpH7qzs5eVTvg.png

Diff commits and branches

Diff branches

git branch --merged master — Which branches are merged with the master, and can be removed?

git branch --no-merged master — Which branches aren’t merged with the master yet?

In this article, we’ve looked at merging in deep, discussed “good” commits, and how we can reference commits. Next time we will talk about how we can fix mistakes. Subscribe to not miss any new updates.


Only registered users can post comments. Please, login or signup.

Start blogging about your favorite technologies and get more readers

Join other developers and claim your FAUN account now!

Avatar

Danylo Halaiko

Student

@d9nich
My code will tell about me better than I about myself. If you want more, watch my LinkedIn profile.
Stats
23

Influence

1k

Total Hits

2

Posts