To find out why I think you should be rebaseing interactively read my first Dev.to post.
I like to write articles using a different perspective than what I used to learn or read. It probably goes along with all my other tools not commonly used. I think I found a way to cover this topic differently.
It is a program, using a domain specific language with very limited scope.
The interactive rebase operats with the domain of commits. What is a commit?
Commits consist of changes to content, author, committer, and parents. The primary two which are manipulated are the content changes and parent.
The script is interpreted from top to bottom. There is no control flow or looping.
The script allows for execution pause, where the user can modify files and the script itself in the middle of script execution.
When interactive rebase starts you are presented with the script in a text editor. At the end of the script is a comment which lists all the commands and their description.
Concider the operations utilized when committing to git. A general workflow could be as follows.
- Modify files
- Add files to git
- Commit files to git
edit - this command pauses execution after commit.
What this means is that git will write the commit to its database and await further instructions. This is most useful when combined with amend (a way of modifying the last commit).
reword - this command pauses at commit.
What this means is that git will present a text editor with the commit message. You can now modify the message associated with the changes.
Note here that
reword pauses earlier than
edit however edit is used to modify files which is an earlier step than committing. Understanding amend is important to use edit at its full power.
pick - this command will utilize the entire commit and continue execution of the script.
break - this is inserted on its own line and just stops scrip execution. Use this if you are wanting to change something before the first commit of your rebase takes place, like if you want to amend a merge commit you're rebaseing onto.
I wanted to pause and call out these next two commands. I believe these are the the most important as they make history rewrite something which can be delayed.
fixup - this command combines the changes of this commit, with the previous commit.
Recall that the scrip execution is from the start of the file, this means
fixup is combined upward in the file.
squash - this command pause on the commit message after combining the changes of this commit, with the previous commit. It would be like fixup-reword if commands could be combined on a commit.
I will stop here, there are additional commands which I have not made use of.
These are not so much commands but script modifications which are useful.
Change the parent commit. This is just a weird way of saying apply a commit in a different order. All you need to do is move the commit line in the order you desire, this functionality is critical to using
drop- this command removes the commit from history. It can also be done by removing the line from the script.
I keep coming back to
fixup because it is so useful.
git commit --fixup <hash>
This creates a new commit but it will not ask for a message, instead the commit is an instrument to fixup the commit at the provided hash.
For more details and alternatives to read autosquashing git commits. Hint
The last key piece to using this is --autosquash.
git rebase -i --autosquash origin/master
This tells git to move the fixup and squash commits adjacent to the commit they operate on. Or configure it
git config --global rebase.autosquash true
This tool is critical in making merge just a little easier to merge or even rebase.
Sometimes commits build up as you work through a problem and it is not orderly. In this case breaking apart commits may be easier by starting from the beginning.
git reset origin/master
This will leave your working tree untouched and nothing committed.
Now it is time to employ a partial commit to build out the more descriptive commits.