Skip to content

Merge commits in pull requests

Pedro M. Baeza edited this page Oct 21, 2023 · 14 revisions

Merge/squash commits in pull requests

It is good practice that every time that you do a pull request, the commit history contains the minimum necessary commit messages.

Merge/squash your own commits

If you have worked locally on some feature, and produced a lot of commits in the process to reach to the final state, the rest of the world does not necessarily need to know your intermediate back and forth activity. You may just want to merge all these commits into a single one, and provide a nice summary of the changes that the commit introduces.

In order to do squash your own commits you can use git rebase -i <first commit SHA>, where <first commit SHA> is the commit SHA from which you want to start the review, or git rebase -i HEAD~N, where N is the number of commits that you have introduced.

Example:

pick 1949129 [IMP] module: Introduce feature A
pick d2cf643 Fix bug 1 of feature A
pick 42bd9e8 Fix bug 2 of feature A
pick 7f767d5 Fix bug 3 of feature A

You want a single commit with one description only, do git rebase HEAD~4. Then change the lines to:

pick 1949129 [IMP] module: Introduce feature A
fixup d2cf643 Fix bug 1 of feature A
fixup 42bd9e8 Fix bug 2 of feature A
fixup 7f767d5 Fix bug 3 of feature A

This produces the following result:

1949129 [IMP] module: Introduce feature A

Merge/squash the commits generated by bots or Weblate

While rescuing the commit history of a module, you can see that between the commits created by the contributors (a module addition, a migration commit, a new feature commit, a fix commit...), the different OCA bots have produced several commits in the middle that makes the commit history look dirty, or at least not in the best compacted way.

The same may happen if a translation is done in Weblate in several time frames, generating several commits across time.

You can merge all those commits together or with the commit that generates them.

Example:

4c88180 (contributor1) [ADD] module_x
2a0f1de (OCA-git-bot) [UPD] README.rst
21fede3 (oca-travis) [UPD] Update module.pot
83526e8 (oca-transbot) Update translation files
00d0e95 (translator1) Added translation using Weblate (Italian)
e34ab12 (translator1) Translated using Weblate (Italian)
b112d0c (contributor2) [FIX] module_x: Fix README explanation
a437b38 (OCA-git-bot) [UPD] README.rst
19891ab (translator1) Translated using Weblate (Italian)
f31004c (translator2) Translated using Weblate (Italian)
5a3fc49 (translator2) Translated using Weblate (Spanish)
922d16b (contributor2) [IMP] module_x: Add a new feature
8f90d6c (oca-travis) [UPD] Update module.pot

In order to squash these administrative commits, use git rebase -i origin/x, where x is the Odoo version (14.0, 15.0, 16.0,...). Don't forget first to do git fetch origin x to get the latest remote information.

On the editor that appears, change the word that indicates the operation, exchanging pick to fixup (or simply f to abbreviate). You can also change the order of the lines to merge several lines that are not consecutive (if it makes sense).

This would be the result for the example:

pick 4c88180 (contributor1) [ADD] module_x
f 2a0f1de (OCA-git-bot) [UPD] README.rst
f 21fede3 (oca-travis) [UPD] Update module.pot
f 83526e8 (oca-transbot) Update translation files
pick 00d0e95 (translator1) Added translation using Weblate (Italian)
f e34ab12 (translator1) Translated using Weblate (Italian)
f 19891ab (translator1) Translated using Weblate (Italian)
pick b112d0c (contributor2) [FIX] module_x: Fix README explanation
f a437b38 (OCA-git-bot) [UPD] README.rst
pick f31004c (translator2) Translated using Weblate (Italian)
pick 5a3fc49 (translator2) Translated using Weblate (Spanish)
pick 922d16b (contributor2) [IMP] module_x: Add a new feature
f 8f90d6c (oca-travis) [UPD] Update module.pot
  • We have squashed all the bot commits with the "real" commit that generates them.
  • We merge together translation commits for the same language coming from the same author. It's OK to merge the commit saying "Added translation using Weblate..." with commits saying "Translated using Weblate...", as both are translations. It's just that Weblate put a different commit message if the translation is new, or if it already exists.
  • We have changed the order of the second Translated using Weblate (Italian), as they come from the same translator and it's the same language, to squash them together.
  • We don't squash translation commits coming from different translators.
  • We don't squash translation commits from the same contributor, but different language.

There's a chance that changing the order of lines, a merge conflict appears. That's because some of the files touched by the commit, are modified on the in-between commits. On that case, you can't squash that commits together and they should be left as is. Abort the operation with git rebase --abort and start again without reordering such commits.

That's why it's recommended to do 2 rebase passes: one with only the fixups that don't modify commit order, and a second one with them, and if any error, iterate the pass only squashing one by one until discovering the conflicting one.

TIP: To ease the recognition of the commit authors in the interactive rebase, you can set git config --global --add rebase.instructionFormat "(%an <%ae>) %s".

TIP 2: If you put GIT_EDITOR=<editor> before the rebase command, where <editor> is the editor executable (nano, vim, gedit), such editor will be used to edit the lines.