Thursday, July 6, 2023

git cherry-pick

    

Currently, I am curious to find out what Git will do for us behind the scene if we run the 'git cherry-pick' commands. Below are the logs coming from my experiment. 


Reference: Git Book


Preparation


Create a brand new folder and run the 'git init' command.


Step 1:



Run the following commands to simulate the situation above.


    $ echo 'c1' > test.txt
$ git add .
$ git commit -m 'c1'
[master (root-commit) ae8f044] c1 1 file changed, 1 insertion(+) create mode 100644 test.txt

    $ echo 'c2' > test.txt
$ git add .
$ git commit -m 'c2'
    [master b719c3c] c2
     1 file changed, 1 insertion(+), 1 deletion(-)

$ git checkout -b dev
Switched to a new branch 'dev'

    $ echo 'c3' > test.txt
$ git add .
$ git commit -m 'c3'
[dev d27e424] c3 1 file changed, 1 insertion(+), 1 deletion(-)

$ git checkout master
Switched to branch 'master'

    $ echo 'c4' > test.txt
$ git add .
$ git commit -m 'c4'
[master 71823ca] c4 1 file changed, 1 insertion(+), 1 deletion(-)

$ git checkout dev
Switched to branch 'dev'

    $ echo 'c5' > test.txt
$ git add .
$ git commit -m 'c5'
[dev ca63078] c5 1 file changed, 1 insertion(+), 1 deletion(-)

$ git checkout master
    Switched to branch 'master'


Check the git status.


    $ 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
│   ├── dev
│   └── master ├── objects
│   ├── 07 │   │   └── 71aea884dd394a7b12783d049f05b5599f41a4 (git blob object for c3) │   ├── 16 │   │   └── f9ec009e5568c435f473ba3a1df732d49ce8c3 (git blob object for c2) │   ├── 3d │   │   └── 3095743da8025788f376069d9c07b9d867d5c1 (git tree object for c4) │   ├── 61 │   │   └── 8ce2788f58e3fb609e5666ab6c433f37423604 (git tree object for c5) │   ├── 71 │   │   └── 823caf53fc21b9909e073361dac6f9e3cfba96 (git commit object for c4) │   ├── a1 │   │   └── 03f673dd1b7c5727aa0ae0100419adc50e1b76 (git blob object for c4) │   ├── ae │   │   ├── 8f0444ccad90b277e3c51220c8d1f1af0cfba0 (git commit object for c1) │   │   └── 9304576a6ec3419b231b2b9c8e33a06f97f9fb (git blob object for c1) │   ├── b5 │   │   └── fab02de1c1f88003afeb7e98cf84a141bff039 (git tree object for c3) │   ├── b7 │   │   └── 19c3c104eefb9edef6b06d190e140f8af62377 (git commit object for c2) │   ├── c0 │   │   └── b072a3d368667939677b9315360631a100ecde (git tree object for c2) │   ├── c3 │   │   └── 6357109ce20af8f90df3c0dd0784e89408d707 (git blob object for c5) │   ├── ca │   │   └── 63078ddb21c6db42795ed3a20a867dee2d9ed8 (git commit object for c5) │   ├── d2 │   │   └── 7e4240f4faf17a95884f009416bfafd88a4572 (git commit object for c3) │   ├── f1 │   │   └── 8c7b882bf09e79d96b692c31450cf59344fbf4 (git tree object for c1)
│   ├── info │   └── pack └── refs ├── heads
│   ├── dev
│   └── master └── tags 26 directories, 39 files


Check more info.


    $ cat .git/HEAD
ref: refs/heads/master

$ cat .git/refs/heads/master
71823caf53fc21b9909e073361dac6f9e3cfba96

$ cat .git/refs/heads/dev
ca63078ddb21c6db42795ed3a20a867dee2d9ed8

$ git ls-files -s
100644 a103f673dd1b7c5727aa0ae0100419adc50e1b76 0 test.txt

$ git log --oneline --decorate --graph --all
* ca63078 (dev) c5 * d27e424 c3 | * 71823ca (HEAD -> master) c4 |/ * b719c3c c2 * ae8f044 c1


Step 2:


Imagine that in the mater branch, we only want the c3 commit from the dev branch commit history.

Run the 'git cherry-pick' command.


    $ git cherry-pick d27e424
Auto-merging test.txt CONFLICT (content): Merge conflict in test.txt error: could not apply d27e424... c3 hint: After resolving the conflicts, mark them with hint: "git add/rm <pathspec>", then run hint: "git cherry-pick --continue". hint: You can instead skip this commit with "git cherry-pick --skip". hint: To abort and get back to the state before "git cherry-pick", hint: run "git cherry-pick --abort".


Resolve the conflict and run 'git cherry-pick --continue'.


$ git cherry-pick --continue
[master 1a42c7d] c3 Date: Thu Jul 6 00:01:02 2023 -0700 1 file changed, 1 insertion(+)


Check the git status.


    $ 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
│   ├── dev
│   └── master ├── objects
│   ├── 07 │   │   └── 71aea884dd394a7b12783d049f05b5599f41a4 (git blob object for c3) │   ├── 16 │   │   └── f9ec009e5568c435f473ba3a1df732d49ce8c3 (git blob object for c2) 
│   ├── 1a │   │   └── 42c7d883cd929afafa268850e139da74e72fc3 (git commit object for new c3) <= NEW │   ├── 21 │   │   └── 280bbd692007b5f635701cef0a31ba95ed5d94 (git tree object for conflict) <= NEW
│   ├── 3d │   │   └── 3095743da8025788f376069d9c07b9d867d5c1 (git tree object for c4) │   ├── 61 │   │   └── 8ce2788f58e3fb609e5666ab6c433f37423604 (git tree object for c5) │   ├── 71 │   │   └── 823caf53fc21b9909e073361dac6f9e3cfba96 (git commit object for c4) 
│   ├── 98 │   │   └── 3a0a8ef586ce632217931ebcb97d18c3f1e781 (git blob object for new c3) <= NEW
│   ├── a1 │   │   └── 03f673dd1b7c5727aa0ae0100419adc50e1b76 (git blob object for c4) │   ├── ae │   │   ├── 8f0444ccad90b277e3c51220c8d1f1af0cfba0 (git commit object for c1) │   │   └── 9304576a6ec3419b231b2b9c8e33a06f97f9fb (git blob object for c1) │   ├── b5 │   │   └── fab02de1c1f88003afeb7e98cf84a141bff039 (git tree object for c3) │   ├── b7 │   │   └── 19c3c104eefb9edef6b06d190e140f8af62377 (git commit object for c2) │   ├── c0 │   │   └── b072a3d368667939677b9315360631a100ecde (git tree object for c2) │   ├── c3 │   │   └── 6357109ce20af8f90df3c0dd0784e89408d707 (git blob object for c5) │   ├── ca │   │   └── 63078ddb21c6db42795ed3a20a867dee2d9ed8 (git commit object for c5) 
│   ├── d2 │   │   └── 7e4240f4faf17a95884f009416bfafd88a4572 (git commit object for c3) │   ├── e2 │   │   └── 061d2d7549cdd5cdeffa40308264cc17b956b9 (git tree object for new c3) <= NEW
│   ├── f1 │   │   └── 8c7b882bf09e79d96b692c31450cf59344fbf4 (git tree object for c1)
│   ├── f5 │   │   └── 7f64e9fadcf897efa1173509cd215908ec4186 (git blob object for conflict) <= NEW
│   ├── info │   └── pack └── refs ├── heads
│   ├── dev
│   └── master └── tags 31 directories, 44 files


Check the conflict objects.


    $ git cat-file -t 21280bb
tree

$ git cat-file -p 21280bb
100644 blob f57f64e9fadcf897efa1173509cd215908ec4186 test.txt

$ git cat-file -p f57f64
<<<<<<< HEAD c4 ======= c3 >>>>>>> d27e424 (c3)


Check more info.


    $ cat .git/HEAD
ref: refs/heads/master

$ cat .git/refs/heads/master
1a42c7d883cd929afafa268850e139da74e72fc3

$ cat .git/refs/heads/dev
ca63078ddb21c6db42795ed3a20a867dee2d9ed8

$ git ls-files -s
100644 983a0a8ef586ce632217931ebcb97d18c3f1e781 0 test.txt

$ git log --oneline --decorate --graph --all
* 1a42c7d (HEAD -> master) c3 * 71823ca c4 | * ca63078 (dev) c5 | * d27e424 c3 |/ * b719c3c c2 * ae8f044 c1



Use the 'git cherry-pick' command, git will rewrite the same commit with the new SHA-1 key (1a42c7d) on top of the current branch.


No comments:

Post a Comment