Currently, I am curious to find out what Git will do for us behind the scene if we run the 'git merge' commands. Below are the logs coming from my experiment.
Reference: Git Book
Introduction
If it is not the linear relationship of the commit history, we cannot use the fast-forward approach.
We need to use the three-way merging.
Take the following as an example, both branches 'master' and 'hotfix' have commits which other branch don't have.
Use the 'git merge' command to merge the hotfix branch to the master branch.
The 'git merge' command will help to create a new merging commit C6, and the parents of C6 are C4 and C5.
Preparation
Create a brand new folder and run the 'git init' command.
Step 1:
Run the following commands to create c1, c2, and c3 commits.
$ git add .
$ git commit -m 'c1'
[master (root-commit) 09c1658] c1
1 file changed, 1 insertion(+)
create mode 100644 test.txt
$ git add .
$ git commit -m 'c2'
[master f3333e2] c2
1 file changed, 1 insertion(+), 1 deletion(-)
$ git add .
$ git commit -m 'c3'
[master c9368a3] c3
1 file changed, 1 insertion(+), 1 deletion(-)
Check the git status.
On branch master
nothing to commit, working tree clean
Check the .git tree structure.
$ tree .git/
.git/
├── COMMIT_EDITMSG
├── HEAD
├── branches
├── config
├── description
├── hooks
│ ├── applypatch-msg.sample
│ ├── commit-msg.sample
│ ├── fsmonitor-watchman.sample
│ ├── post-update.sample
│ ├── pre-applypatch.sample
│ ├── pre-commit.sample
│ ├── pre-merge-commit.sample
│ ├── pre-push.sample
│ ├── pre-rebase.sample
│ ├── pre-receive.sample
│ ├── prepare-commit-msg.sample
│ ├── push-to-checkout.sample
│ └── update.sample
├── index
├── info
│ └── exclude
├── logs
│ ├── HEAD
│ └── refs
│ └── heads
│ └── master
├── objects
│ ├── 07
│ │ └── 71aea884dd394a7b12783d049f05b5599f41a4 (git blob object for c3)
│ ├── 09
│ │ └── c165883d0a25f729d9a7c69fa02efd6c87c618 (git commit object for c1)
│ ├── 16
│ │ └── f9ec009e5568c435f473ba3a1df732d49ce8c3 (git blob object for c2)
│ ├── ae
│ │ └── 9304576a6ec3419b231b2b9c8e33a06f97f9fb (git blob object for c1)
│ ├── b5
│ │ └── fab02de1c1f88003afeb7e98cf84a141bff039 (git tree object for c3)
│ ├── c0
│ │ └── b072a3d368667939677b9315360631a100ecde (git tree object for c2)
│ ├── c9
│ │ └── 368a318142494f31acd9c83a9763ed9f395a3b (git commit object for c3)
│ ├── f1
│ │ └── 8c7b882bf09e79d96b692c31450cf59344fbf4 (git tree object for c1)
│ ├── f3
│ │ └── 333e2df7930fa29ef8fb7ee177388f4a02b039 (git commit object for c2)
│ ├── info
│ └── pack
└── refs
├── heads
│ └── master
└── tags
21 directories, 31 files
Check more info.
$ cat .git/HEAD
ref: refs/heads/master
$ cat .git/refs/heads/master
c9368a318142494f31acd9c83a9763ed9f395a3b
$ git ls-files -s
100644 0771aea884dd394a7b12783d049f05b5599f41a4 0 test.txt
$ git log --oneline --decorate --graph --all
* c9368a3 (HEAD -> master) c3
* f3333e2 c2
* 09c1658 c1
Step 2:
Create and checkout a new branch 'hotfix'.
Switched to a new branch 'hotfix'
Check the git status.
On branch hotfix
nothing to commit, working tree clean
Check the .git tree structure.
$ tree .git/
.git/
├── COMMIT_EDITMSG
├── HEAD
├── branches
├── config
├── description
├── hooks
│ ├── applypatch-msg.sample
│ ├── commit-msg.sample
│ ├── fsmonitor-watchman.sample
│ ├── post-update.sample
│ ├── pre-applypatch.sample
│ ├── pre-commit.sample
│ ├── pre-merge-commit.sample
│ ├── pre-push.sample
│ ├── pre-rebase.sample
│ ├── pre-receive.sample
│ ├── prepare-commit-msg.sample
│ ├── push-to-checkout.sample
│ └── update.sample
├── index
├── info
│ └── exclude
├── logs
│ ├── HEAD
│ └── refs
│ └── heads
│ ├── hotfix
│ └── master
├── objects
│ ├── 07
│ │ └── 71aea884dd394a7b12783d049f05b5599f41a4 (git blob object for c3)
│ ├── 09
│ │ └── c165883d0a25f729d9a7c69fa02efd6c87c618 (git commit object for c1)
│ ├── 16
│ │ └── f9ec009e5568c435f473ba3a1df732d49ce8c3 (git blob object for c2)
│ ├── ae
│ │ └── 9304576a6ec3419b231b2b9c8e33a06f97f9fb (git blob object for c1)
│ ├── b5
│ │ └── fab02de1c1f88003afeb7e98cf84a141bff039 (git tree object for c3)
│ ├── c0
│ │ └── b072a3d368667939677b9315360631a100ecde (git tree object for c2)
│ ├── c9
│ │ └── 368a318142494f31acd9c83a9763ed9f395a3b (git commit object for c3)
│ ├── f1
│ │ └── 8c7b882bf09e79d96b692c31450cf59344fbf4 (git tree object for c1)
│ ├── f3
│ │ └── 333e2df7930fa29ef8fb7ee177388f4a02b039 (git commit object for c2)
│ ├── info
│ └── pack
└── refs
├── heads
│ ├── hotfix
│ └── master
└── tags
21 directories, 33 files
Check more info.
$ cat .git/HEAD
ref: refs/heads/hotfix
$ cat .git/refs/heads/master
c9368a318142494f31acd9c83a9763ed9f395a3b
$ cat .git/refs/heads/hotfix
c9368a318142494f31acd9c83a9763ed9f395a3b
$ git ls-files -s
100644 0771aea884dd394a7b12783d049f05b5599f41a4 0 test.txt
$ git log --oneline --decorate --graph --all
* c9368a3 (HEAD -> hotfix, master) c3
* f3333e2 c2
* 09c1658 c1
Both the hotfix branch and the master branch point to the c3 commit.
Step 3:
Create a new commit 'c4' on the hotfix branch.
$ echo 'c4' > test.txt
$ git add .
$ git commit -m 'c4'
[hotfix 85ad7e6] c4
1 file changed, 1 insertion(+), 1 deletion(-)
Check the git status.
On branch hotfix
nothing to commit, working tree clean
Check the .git tree structure.
$ tree .git/
.git/
├── COMMIT_EDITMSG
├── HEAD
├── branches
├── config
├── description
├── hooks
│ ├── applypatch-msg.sample
│ ├── commit-msg.sample
│ ├── fsmonitor-watchman.sample
│ ├── post-update.sample
│ ├── pre-applypatch.sample
│ ├── pre-commit.sample
│ ├── pre-merge-commit.sample
│ ├── pre-push.sample
│ ├── pre-rebase.sample
│ ├── pre-receive.sample
│ ├── prepare-commit-msg.sample
│ ├── push-to-checkout.sample
│ └── update.sample
├── index
├── info
│ └── exclude
├── logs
│ ├── HEAD
│ └── refs
│ └── heads
│ ├── hotfix
│ └── master
├── objects
│ ├── 07
│ │ └── 71aea884dd394a7b12783d049f05b5599f41a4 (git blob object for c3)
│ ├── 09
│ │ └── c165883d0a25f729d9a7c69fa02efd6c87c618 (git commit object for c1)
│ ├── 16
│ │ └── f9ec009e5568c435f473ba3a1df732d49ce8c3 (git blob object for c2)
│ ├── 3d
│ │ └── 3095743da8025788f376069d9c07b9d867d5c1 (git tree object for c4)
│ ├── 85
│ │ └── ad7e6b045bfc28bf4546a86f1e9b0b669fc034 (git commit object for c4)
│ ├── a1
│ │ └── 03f673dd1b7c5727aa0ae0100419adc50e1b76 (git blob object for c4)
│ ├── ae
│ │ └── 9304576a6ec3419b231b2b9c8e33a06f97f9fb (git blob object for c1)
│ ├── b5
│ │ └── fab02de1c1f88003afeb7e98cf84a141bff039 (git tree object for c3)
│ ├── c0
│ │ └── b072a3d368667939677b9315360631a100ecde (git tree object for c2)
│ ├── c9
│ │ └── 368a318142494f31acd9c83a9763ed9f395a3b (git commit object for c3)
│ ├── f1
│ │ └── 8c7b882bf09e79d96b692c31450cf59344fbf4 (git tree object for c1)
│ ├── f3
│ │ └── 333e2df7930fa29ef8fb7ee177388f4a02b039 (git commit object for c2)
│ ├── info
│ └── pack
└── refs
├── heads
│ ├── hotfix
│ └── master
└── tags
24 directories, 36 files
Check more info.
$ cat .git/HEAD
ref: refs/heads/hotfix
$ cat .git/refs/heads/master
c9368a318142494f31acd9c83a9763ed9f395a3b
$ cat .git/refs/heads/hotfix
85ad7e6b045bfc28bf4546a86f1e9b0b669fc034
$ git ls-files -s
100644 a103f673dd1b7c5727aa0ae0100419adc50e1b76 0 test.txt
$ git log --oneline --decorate --graph --all
* 85ad7e6 (HEAD -> hotfix) c4
* c9368a3 (master) c3
* f3333e2 c2
* 09c1658 c1
Now the hotfix branch has one more commit ahead the master branch.
Step 4:
Switch to the master branch.
Create a commit c5 (make sure to avoid conflict).
$ git checkout master
Switched to branch 'master'
$ echo 'c5' > c5.txt
$ git add .
$ git commit -m 'c5'
[master 25e3699] c5
1 file changed, 1 insertion(+)
create mode 100644 c5.txt
Check the git status.
On branch master
nothing to commit, working tree clean
Check the .git tree structure.
$ tree .git/
.git/
├── COMMIT_EDITMSG
├── HEAD
├── branches
├── config
├── description
├── hooks
│ ├── applypatch-msg.sample
│ ├── commit-msg.sample
│ ├── fsmonitor-watchman.sample
│ ├── post-update.sample
│ ├── pre-applypatch.sample
│ ├── pre-commit.sample
│ ├── pre-merge-commit.sample
│ ├── pre-push.sample
│ ├── pre-rebase.sample
│ ├── pre-receive.sample
│ ├── prepare-commit-msg.sample
│ ├── push-to-checkout.sample
│ └── update.sample
├── index
├── info
│ └── exclude
├── logs
│ ├── HEAD
│ └── refs
│ └── heads
│ ├── hotfix
│ └── master
├── objects
│ ├── 07
│ │ └── 71aea884dd394a7b12783d049f05b5599f41a4 (git blob object for c3)
│ ├── 09
│ │ └── c165883d0a25f729d9a7c69fa02efd6c87c618 (git commit object for c1)
│ ├── 16
│ │ └── f9ec009e5568c435f473ba3a1df732d49ce8c3 (git blob object for c2)
│ ├── 25
│ │ └── e3699293eeeb9b6f4e33e5873171b6aba01e80 (git commit object for c5)
│ ├── 3d
│ │ └── 3095743da8025788f376069d9c07b9d867d5c1 (git tree object for c4)
│ ├── 85
│ │ └── ad7e6b045bfc28bf4546a86f1e9b0b669fc034 (git commit object for c4)
│ ├── 9a
│ │ └── ed71345f7f6af10cf15445dcc767b5f3433ae7 (git tree object for c5)
│ ├── a1
│ │ └── 03f673dd1b7c5727aa0ae0100419adc50e1b76 (git blob object for c4)
│ ├── ae
│ │ └── 9304576a6ec3419b231b2b9c8e33a06f97f9fb (git blob object for c1)
│ ├── b5
│ │ └── fab02de1c1f88003afeb7e98cf84a141bff039 (git tree object for c3)
│ ├── c0
│ │ └── b072a3d368667939677b9315360631a100ecde (git tree object for c2)
│ ├── c3
│ │ └── 6357109ce20af8f90df3c0dd0784e89408d707 (git blob object for c5)
│ ├── c9
│ │ └── 368a318142494f31acd9c83a9763ed9f395a3b (git commit object for c3)
│ ├── f1
│ │ └── 8c7b882bf09e79d96b692c31450cf59344fbf4 (git tree object for c1)
│ ├── f3
│ │ └── 333e2df7930fa29ef8fb7ee177388f4a02b039 (git commit object for c2)
│ ├── info
│ └── pack
└── refs
├── heads
│ ├── hotfix
│ └── master
└── tags
27 directories, 39 files
Check more info.
$ cat .git/HEAD
ref: refs/heads/master
$ cat .git/refs/heads/master
25e3699293eeeb9b6f4e33e5873171b6aba01e80
$ cat .git/refs/heads/hotfix
85ad7e6b045bfc28bf4546a86f1e9b0b669fc034
$ git ls-files -s
100644 c36357109ce20af8f90df3c0dd0784e89408d707 0 c5.txt
100644 0771aea884dd394a7b12783d049f05b5599f41a4 0 test.txt
$ git log --oneline --decorate --graph --all
* 25e3699 (HEAD -> master) c5
| * 85ad7e6 (hotfix) c4
|/
* c9368a3 c3
* f3333e2 c2
* 09c1658 c1
Now the commit history is diverged.
Step 5:
Run the 'git merge' command to merge the work from the hotfix branch.
Below is a prompt message:
----------------------------------------
Merge branch 'hotfix'
# Please enter a commit message to explain why this merge is necessary,
# especially if it merges an updated upstream into a topic branch.
#
# Lines starting with '#' will be ignored, and an empty message aborts
# the commit.
----------------------------------------
Merge made by the 'ort' strategy.
test.txt | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
Then the auto-generated merging commit was created.
Check the git status.
On branch master
nothing to commit, working tree clean
Check the .git tree structure.
$ tree .git/
.git/
├── COMMIT_EDITMSG
├── HEAD
├── ORIG_HEAD
├── branches
├── config
├── description
├── hooks
│ ├── applypatch-msg.sample
│ ├── commit-msg.sample
│ ├── fsmonitor-watchman.sample
│ ├── post-update.sample
│ ├── pre-applypatch.sample
│ ├── pre-commit.sample
│ ├── pre-merge-commit.sample
│ ├── pre-push.sample
│ ├── pre-rebase.sample
│ ├── pre-receive.sample
│ ├── prepare-commit-msg.sample
│ ├── push-to-checkout.sample
│ └── update.sample
├── index
├── info
│ └── exclude
├── logs
│ ├── HEAD
│ └── refs
│ └── heads
│ ├── hotfix
│ └── master
├── objects
│ ├── 07
│ │ └── 71aea884dd394a7b12783d049f05b5599f41a4 (git blob object for c3)
│ ├── 09
│ │ └── c165883d0a25f729d9a7c69fa02efd6c87c618 (git commit object for c1)
│ ├── 16
│ │ └── f9ec009e5568c435f473ba3a1df732d49ce8c3 (git blob object for c2)
│ ├── 25
│ │ └── e3699293eeeb9b6f4e33e5873171b6aba01e80 (git commit object for c5)
│ ├── 3d
│ │ └── 3095743da8025788f376069d9c07b9d867d5c1 (git tree object for c4)
│ ├── 60
│ │ └── 0188dcf6aa195ed51c91212610f0ab42b29f43 (git tree object for merge commit)
│ ├── 71
│ │ └── a62be3c4950898a454f6057f353678b542b920 (git commit object for merge commit)
│ ├── 85
│ │ └── ad7e6b045bfc28bf4546a86f1e9b0b669fc034 (git commit object for c4)
│ ├── 9a
│ │ └── ed71345f7f6af10cf15445dcc767b5f3433ae7 (git tree object for c5)
│ ├── a1
│ │ └── 03f673dd1b7c5727aa0ae0100419adc50e1b76 (git blob object for c4)
│ ├── ae
│ │ └── 9304576a6ec3419b231b2b9c8e33a06f97f9fb (git blob object for c1)
│ ├── b5
│ │ └── fab02de1c1f88003afeb7e98cf84a141bff039 (git tree object for c3)
│ ├── c0
│ │ └── b072a3d368667939677b9315360631a100ecde (git tree object for c2)
│ ├── c3
│ │ └── 6357109ce20af8f90df3c0dd0784e89408d707 (git blob object for c5)
│ ├── c9
│ │ └── 368a318142494f31acd9c83a9763ed9f395a3b (git commit object for c3)
│ ├── f1
│ │ └── 8c7b882bf09e79d96b692c31450cf59344fbf4 (git tree object for c1)
│ ├── f3
│ │ └── 333e2df7930fa29ef8fb7ee177388f4a02b039 (git commit object for c2)
│ ├── info
│ └── pack
└── refs
├── heads
│ ├── hotfix
│ └── master
└── tags
29 directories, 42 files
Check the content of the git commit object '71a62be'
$ git cat-file -p 71a62be
tree 600188dcf6aa195ed51c91212610f0ab42b29f43
parent 25e3699293eeeb9b6f4e33e5873171b6aba01e80
parent 85ad7e6b045bfc28bf4546a86f1e9b0b669fc034
author Frank <frank@demo.com> datetime
committer Frank <frank@demo.com> datetime
Merge branch 'hotfix'
This merge commit has two parents: commit c4 and c5.
Check more info.
$ cat .git/HEAD
ref: refs/heads/master
$ cat .git/ORIG_HEAD
25e3699293eeeb9b6f4e33e5873171b6aba01e80
$ cat .git/refs/heads/master
71a62be3c4950898a454f6057f353678b542b920
$ cat .git/refs/heads/hotfix
85ad7e6b045bfc28bf4546a86f1e9b0b669fc034
$ git ls-files -s
100644 c36357109ce20af8f90df3c0dd0784e89408d707 0 c5.txt
100644 a103f673dd1b7c5727aa0ae0100419adc50e1b76 0 test.txt
$ git log --oneline --decorate --graph --all
* 71a62be (HEAD -> master) Merge branch 'hotfix'
|\
| * 85ad7e6 (hotfix) c4
* | 25e3699 c5
|/
* c9368a3 c3
* f3333e2 c2
* 09c1658 c1
No comments:
Post a Comment