Skip to content

Using git to prepare your PR to have a clean history

Brice Dutheil edited this page Jan 1, 2015 · 1 revision

Using git to prepare your PR to have a clean history

Tests in any project are a valuable asset, so is a clean version history. Having a proper and clean commits helps to review and understand changes. Git is an awesome tool that let you control how you want your history. GitHub just use the history of the branch, so each time the history is changed the PR is updated with the actual history. GitHub PR is a fantastic way to have changes review before merge.

The following tips may help you if you are not proficient in git, but they consists hardly in a bullet proof tutorial, knowing git is the most bullet proof skill. But the steps of the following options can guide you to have a clean history.

There are multiple blog entries explaining git, I find the following two quite compelling and showing a modern way to do things right in git, of course StackOverflow is another great source.

Note these action rewrite history, and it's easy to get lost, in git there multiple ways to fix things and to prevent errors, for example it is possible to create a backup branch before starting something that may go wrong.

Basically the most common way to rewrite history are amending, rebasing interactively, and sqaushing.

amending

You can amend commits if they don't add semantic value to the PR. For example an history like this in your own PR branch can be avoided.

* 5a03bf5 - fix another bug
* ccc50cc - fix npe stuff
* 18d8ace - Added new awesome feature

If the two fix change where amended with such command line (--no-edit tell git to don't edit the message of the previous commit)

git commit --amend --no-edit

Instead you will have a single meaningful commit

* 98a826e - Added new awesome feature

rebasing interactively

If for some reason a change has to be made afterward, for whatever reasons: review, a bug fix, adding a missing stuff, javadoc etc. The history can then be chaotic.

* a2d6ee9 - Review fixes
* eed23a1 - Complete awesome feature with better error message
* 84aaad2 - wip
* 24fe90a - Merge from somewhere else
* 5a03bf5 - fix another bug
* ccc50cc - fix npe stuff
* 18d8ace - Added new awesome feature

Multiple commit just create nooise in the PR, and they don't help to understand the change, even less when the history has to be read again. To clean that history yuo have to use the git's interactive rebase

git rebase --interactive HEAD~7

It will open on aditor with the 7 chosen commits (in the opposite order) :

pick 18d8ace Added new awesome feature
pick ccc50cc fix npe stuff
pick 5a03bf5 fix another bug
pick 24fe90a Merge from somewhere else
pick 84aaad2 wip
pick eed23a1 Complete awesome feature with better error message
pick a2d6ee9 Review fixes

For each line (commits) you can do different possible actions.

pick 18d8ace Added new awesome feature
fixup ccc50cc fix npe stuff
fixup 5a03bf5 fix another bug
pick 24fe90a Merge from somewhere else
squash 84aaad2 wip
squash eed23a1 Complete awesome feature with better error message
pick a2d6ee9 Review fixes

In the above abstract I wrote several action that git will perform interactively. The fixup command tells git to amend the commit without changing the message. The squash command tells git to amend the commit and ask in an editor what is the message of the new commit. This will result in the following history :

* 72d6ac9 - Review fixes
* abe934f - Better error messages for awesome feature
* 73a6abe - Added new awesome feature

just squashing

Sometime however having a single commit is just the right thing to do. With the following history :

* a2d6ee9 - Review fixes
* eed23a1 - Complete awesome feature with better error message
* 84aaad2 - wip
* 24fe90a - Merge from somewhere else
* 5a03bf5 - fix another bug
* ccc50cc - fix npe stuff
* 18d8ace - Added new awesome feature

You can do that

git reset --soft HEAD~7
git commit --message="Adds awesome feature"

pushing the branch with modified history

If everything is ok just perform a push force, it is required as the history has changed and git forbids push that modify the history on the remote, that's why we need to indicate git it's ok.

The follwoing command specify the remote and the branch, it is important if using git with a version inferior to 2.0.0, see more about the push.default config

git push -f origin pr_that_improve_stuffs

Now you should see changes in the PR.