git.day/5 • See all at git.day
Git history tells a story. Tell the best story you can using rebase.
If you need to make changes to commits older than HEAD, an interactive rebase session is a great way to do it. For example, given a graph of commits produced by Git of the day #4: git log --oneline --graph that look like this:
* (master) ffff F
| * (HEAD -> foo) eeee E
| * dddd D
| * cccc C
|/
* bbbb B
* aaaa A
Having done some work on the foo branch, three commits were made. If C and D do not need to be separate commits, rebase can be used to squash them. Specifying the rebase should be of C to HEAD can be done with git rebase -i HEAD~
2. This opens your Git editor with a file showing the 3 commits.
pick cccc C
pick dddd D
pick eeee E
The verb beginning the line is the operation to perform on the commit. pick
is the default that keeps the commit as normal, but there are a whole bunch of verbs that can be used.
To stop and modify a commit in the list, use reword to edit the commit message or edit to also edit the commit content (then use git rebase --continue
). In this case, we not only want to make a change to one commit but to combine the contents of two commits into one. Two verbs to do this are squash and fixup; the former opens an editor for the commit message starting with the two commit messages concatenated, and the latter discards the commit message of the commit being fixup’d.
pick cccc C
fixup dddd D
pick eeee E
This combines C and D, producing the following commit history:
* (master) ffff F
| * (HEAD -> foo) eeeh E’
| * cccg C’
|/
* bbbb B
* aaaa A
C’ and E’ are new commits present on the foo branch and remain branched off commit B.