Wednesday, July 12, 2023

git rebase -i

     

Currently, I am curious to find out what Git will do for us behind the scene if we run the 'git rebase -i' 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' > c1.txt
$ git add .
$ git commit -m 'c1'
[master (root-commit) db67b83] c1 1 file changed, 1 insertion(+) create mode 100644 c1.txt

    $ echo 'c2' > c2.txt
$ git add .
$ git commit -m 'c2'
    [master 9ce38c8] c2
     1 file changed, 1 insertion(+)
     create mode 100644 c2.txt

    $ echo 'c3' > c3.txt
$ git add .
$ git commit -m 'c3'
[master 0cb5816] c3 1 file changed, 1 insertion(+) create mode 100644 c3.txt

    $ echo 'c4' > c4.txt
$ git add .
$ git commit -m 'c4'
[master 82098e7] c4 1 file changed, 1 insertion(+) create mode 100644 c4.txt


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
│   └── master ├── objects
│   ├── 07 │   │   └── 71aea884dd394a7b12783d049f05b5599f41a4 (git blob object for c3) │   ├── 0c │   │   └── b5816af1824bf60da8b472b8752bf5a4805be1 (git commit object for c3) │   ├── 16 │   │   └── f9ec009e5568c435f473ba3a1df732d49ce8c3 (git blob object for c2) 
│   ├── 55 │   │   └── 4b493ae2938685a42afe6b6db5b43718cd6288 (git tree object for c4)  │   ├── 82 │   │   └── 098e7689178db6638f193ceb32f5ed807b73ca (git commit object for c4) 
│   ├── 83 │   │   └── 5da11381dee94c71a04164cdaa533d0673e4e5 (git tree object for c1) │   ├── 96 │   │   └── 8a4b6caa8b55a68098e0495fbd9e75a7d05efa (git tree object for c2) │   ├── 9c │   │   └── e38c88738074a43829866d92b9fccd0365e012 (git commit object for c2) 
│   ├── a1 │   │   └── 03f673dd1b7c5727aa0ae0100419adc50e1b76 (git blob object for c4) 
│   ├── ae │   │   └── 9304576a6ec3419b231b2b9c8e33a06f97f9fb (git blob object for c1) │   ├── db │   │   └── 67b8366893a7726d3149b959245ddafe6db70f (git commit object for c1) │   ├── fc │   │   └── 88a9c9de3667ac068fa176bb960ed4b22c5d4a (git tree object for c3)
│   ├── info │   └── pack └── refs ├── heads
│   └── master └── tags 24 directories, 34 files


Check more info.


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

$ cat .git/refs/heads/master
82098e7689178db6638f193ceb32f5ed807b73ca

$ git ls-files -s
100644 ae9304576a6ec3419b231b2b9c8e33a06f97f9fb 0 c1.txt 100644 16f9ec009e5568c435f473ba3a1df732d49ce8c3 0 c2.txt 100644 0771aea884dd394a7b12783d049f05b5599f41a4 0 c3.txt
100644 a103f673dd1b7c5727aa0ae0100419adc50e1b76 0 c4.txt

$ git log --oneline --decorate --graph --all
* 82098e7 (HEAD -> master) c4 * 0cb5816 c3
* 9ce38c8 c2 * db67b83 c1


Step 2:


Run the 'git rebase -i db67b83' command.


    $ git rebase -i db67b83

  //------------------Prompt Message ----------------------
pick 9ce38c8 c2
pick 0cb5816 c3
pick 82098e7 c4
# Rebase db67b83..82098e7 onto db67b83(3 commands)
#
# Commands:
# p, pick <commit> = use commit
# r, reword <commit> = use commit, but edit the commit message
# e, edit <commit> = use commit, but stop for amending
# s, squash <commit> = use commit, but meld into previous commit
# f, fixup [-C | -c] <commit> = like "squash" but keep only the previous
#                    commit's log message, unless -C is used, in which case
#                    keep only this commit's message; -c is same as -C but
#                    opens the editor
# x, exec <command> = run command (the rest of the line) using shell
# b, break = stop here (continue rebase later with 'git rebase --continue')
# d, drop <commit> = remove commit
# l, label <label> = label current HEAD with a name
# t, reset <label> = reset HEAD to a label
# m, merge [-C <commit> | -c <commit>] <label> [# <oneline>]
# .       create a merge commit using the original merge commit's
# .       message (or the oneline, if no original merge commit was
# .       specified); use -c <commit> to reword the commit message
#
# These lines can be re-ordered; they are executed from top to bottom.
#
# If you remove a line here THAT COMMIT WILL BE LOST.
#
# However, if you remove everything, the rebase will be aborted.
//----------------------------------------


Let us change the message as the following:

Drop the c2 commit and change the order of the C4 and C3 commits.


  //------------------Prompt Message ----------------------
drop 9ce38c8 c2
pick 82098e7 c4
pick 0cb5816 c3
//----------------------------------------

Successfully rebased and updated refs/heads/master.


Check the git status.


    $ git status
On branch master nothing to commit, working tree clean


Check the .git tree structure.


    $ tree .git/
.git/ ├── AUTO_MERGE
├── 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
│   └── master ├── objects
│   ├── 07 │   │   └── 71aea884dd394a7b12783d049f05b5599f41a4 (git blob object for c3) │   ├── 0c │   │   └── b5816af1824bf60da8b472b8752bf5a4805be1 (git commit object for c3) │   ├── 16 │   │   └── f9ec009e5568c435f473ba3a1df732d49ce8c3 (git blob object for c2) 
│   ├── 22
│   │   └── ccdb6783ef6f2ebfae9a534995451f648c6e38 (git commit object for new c3) <= NEW
│   ├── 55 │   │   └── 4b493ae2938685a42afe6b6db5b43718cd6288 (git tree object for c4)  │   ├── 59 │   │   └── 4d3351074627c9137889a75978f0df9d1cc6bd (git commit object for new c4) <= NEW
│   ├── 82 │   │   └── 098e7689178db6638f193ceb32f5ed807b73ca (git commit object for c4) 
│   ├── 83 │   │   └── 5da11381dee94c71a04164cdaa533d0673e4e5 (git tree object for c1) │   ├── 96 │   │   └── 8a4b6caa8b55a68098e0495fbd9e75a7d05efa (git tree object for c2) │   ├── 9c │   │   └── e38c88738074a43829866d92b9fccd0365e012 (git commit object for c2) 
│   ├── a1 │   │   └── 03f673dd1b7c5727aa0ae0100419adc50e1b76 (git blob object for c4) 
│   ├── a6 │   │   └── 2c41aa34590add113a96265734f74754ea2ee9 (git tree object for new c3) <= NEW
│   ├── ae │   │   └── 9304576a6ec3419b231b2b9c8e33a06f97f9fb (git blob object for c1) │   ├── db │   │   └── 67b8366893a7726d3149b959245ddafe6db70f (git commit object for c1) 
│   ├── dc │   │   └── 813e91d4835e21e01f4917a510a0c95824a2da (git tree object for new c4) <= NEW
│   ├── fc │   │   └── 88a9c9de3667ac068fa176bb960ed4b22c5d4a (git tree object for c3)
│   ├── info │   └── pack └── refs ├── heads
│   └── master └── tags 28 directories, 40 files


Check more info.


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

$ cat .git/ORIG_HEAD
82098e7689178db6638f193ceb32f5ed807b73ca

$ cat .git/AUTO_MERGE
a62c41aa34590add113a96265734f74754ea2ee9

$ cat .git/refs/heads/master
22ccdb6783ef6f2ebfae9a534995451f648c6e38

$ git ls-files -s
100644 ae9304576a6ec3419b231b2b9c8e33a06f97f9fb 0 c1.txt 100644 0771aea884dd394a7b12783d049f05b5599f41a4 0 c3.txt
100644 a103f673dd1b7c5727aa0ae0100419adc50e1b76 0 c4.txt

$ git log --oneline --decorate --graph --all
* 22ccdb6 (HEAD -> master) c3 * 594d335 c4 * db67b83 c1


After rebasing (interactive mode), we can remove commits, and we can reorder the commits (swap c3 and c4).


No comments:

Post a Comment