Reassembling commits

One of the widest uses of the git rebase command is for reordering or combining commits. For this first approach, imagine you have to combine two different commits.

Suppose we erroneously added half a grape in the shoppingList.txt file, then the other half, but at the end we want to have only one commit for the entire grape; follow me with these steps.

Add a gr to the shopping list file:

[1] ~/grocery (master)
$ echo -n "gr" >> shoppingList.txt

The -n option is for not adding a new line.

Cat the file to be sure:

[2] ~/grocery (master)
$ cat shoppingList.txt
banana
apple
orange
peach
gr

Now perform the first commit:

[3] ~/grocery (master)
$ git commit -am "Add half a grape"
[master edac12c] Add half a grape
 1 file changed, 1 insertion(+)

Okay, we have a commit with half a grape. Go on and add the other half, ape:

[4] ~/grocery (master)
$ echo -n "ape" >> shoppingList.txt

Check the file:

[5] ~/grocery (master)
$ cat shoppingList.txt
banana
apple
orange
peach
grape

Perform the second commit:

[6] ~/grocery (master)
$ git commit -am "Add the other half of the grape"
[master 4142ad9] Add the other half of the grape
 1 file changed, 1 insertion(+), 1 deletion(-)

Check the log:

[7] ~/grocery (master)
$ git log --oneline --graph --decorate --all
* 4142ad9 (HEAD -> master) Add the other half of the grape
* edac12c Add half a grape
* 603b9d1 Add a peach
| * a8c6219 (melons) Add a watermelon
| * ef6c382 (berries) Add a blackberry
|/
* 0e8b5cf Add an orange
* e4a5e7b Add an apple
* a57d783 Add a banana to the shopping list

Well, this is inconvenient: I'd like to have only a commit with the entire grape.

We can repair the mistake with an interactive rebase. To do this, we have to rebase the last two commits, creating a new one that is, in fact, the sum of the two.

So, type git rebase -i HEAD~2 and see what happen; -i means interactive, while the HEAD~2 argument means I want to rebase the last two commits.

This is a screenshot of the console:

As you can see in the preceding screenshot, Git opens the default editor, Vim. Then it tells us how to edit this temporary file (you can see the location at the bottom of the screenshot) using some commented lines (those starting with #).

Let's read this message carefully.

Here we can reorder the commit lines; doing only this, we basically change the order of commits in our repository. Maybe this can seem a not-so-useful feature, but it can be so if you plan to create new branches after this rebase and you want to clear the ground before.

Then you can delete lines: if you delete a line, basically you drop the corresponding commit.

Finally, for every line (every commit), you can use one of the following commands, as per the comments showed in the Vi editor:

  • # p, pick = use commit: If you pick a commit, the commit will continue to be part of your repo. Think at it as, Okay, I want to preserve this commit as is.
  • # r, reword = use commit, but edit the commit message: Reword allows you to change the commit message, useful if you realized you wrote something wrong in it. It's kind of, Okay, I want to preserve this commit, but I want to change the message.
  • # e, edit = use commit, but stop for amending: When you amend a commit you basically want to reassemble it. For example, you forgot to include a file in it, or you added one too many. If you mark a commit to be edited, Git will stop the subsequent rebase operations to let you do what you need. So, the commit will be preserved, but it will be altered.
  • # s, squash = use commit, but meld into previous commit: Squash is a term we will see again; it basically means put together two commits or more. In this case, if you squash a commit, it will be removed, but the changes within it will be part of the preceding commit. This is maybe the command we need?
  • # f, fixup = like "squash", but discard this commit's log message: Fixup is like squash, but let's provide you with a new commit message. This is definitely what I need; as I want the new grape commit to have a new message.
  • # x, exec = run command (the rest of the line) using shell: Exec is, well, advanced stuff. You basically tell Git to run a particular command when it will manipulate this commit during the following rebase actions. This can be useful to do something you forgot between two commits, rerun some tests, or whatever.
  • # d, drop = remove commit: Drop simply removes the commit, the same as deleting the entire line.

Okay, now we can proceed. We have to modify this file using those commands, and then save it and exit: Git will then continue the rebase process executing every command in order, from top to bottom.

To resolve our issue, I will reword the first commit and then fixup the second; the following is a screenshot of my console:

Note that you can use the long format of the command or the short one (for example, f -> short, fixup -> long).

Okay, now Git does the work and then opens a new temporary file to allow us to write the new message for the commit we decided to reword, that is, the first one. The following is the screenshot:

Note as Git tell us word for word what it is going to do.

Now edit the message, and then save and exit, like in the following screenshot:

Press ENTER and we're done.

This is the final message from Git:

[8] ~/grocery (master)
$ git rebase -i HEAD~2
unix2dos: converting file C:/Users/san/Google Drive/Packt/PortableGit/home/grocery/[detached HEAD 53c73dd] Add a grape
 Date: Sat Aug 26 14:00:58 2017 +0200
 1 file changed, 1 insertion(+)
Successfully rebased and updated refs/heads/master.

Take a look at the log:

[9] ~/grocery (master)
$ git log --oneline --graph --decorate --all
* 6409527 (HEAD -> master) Add a grape
* 603b9d1 Add a peach
| * a8c6219 (melons) Add a watermelon
| * ef6c382 (berries) Add a blackberry
|/
* 0e8b5cf Add an orange
* e4a5e7b Add an apple
* a57d783 Add a banana to the shopping list

Wonderful! We just accomplished our mission.

Now let's make a little experiment on rebasing branches.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.220.1.239