So one of my colleagues attempted to merge a branch using GitHub's "merge via fast-forward" option in the web-interface, to keep the history clean from bogus merge commits (the master
branch into which they merged, had not progressed since the to-be merged feature-branch was started).
Funnily enough, this didn't work as expected: all the commits got new commit-hashes.
On closer inspection, it seems that merge-option is actually called "Rebase and Merge" and it really seems to do the equivalent of git rebase --force
, changing the Committer information (both the person who did the merge, and the time when the merge happened).
It took me quite a while to confirm my suspicion that this is indeed the case, as I couldn't make the cmdline tools to show me the difference between the original commits on the feature branch and the seemingly-identical commits (with different hashes) on the master branch. (In the end, I found that gitk
shows both Committer and Author of a commit; in the very end I found that I can also get this information via git log --pretty=raw
)
So:
git rebase
without the --force
master
)Fast forward merge can be performed when there is a direct linear path from the source branch to the target branch. In fast-forward merge, git simply moves the source branch pointer to the target branch pointer without creating an extra merge commit.
Fast-forward merges literally move your main branch's tip forward to the end of your feature branch. This keeps all commits created in your feature branch sequential while integrating it neatly back into your main branch.
As stated above, Git's default is to use fast-forward merge. It will take the commits from the branch being merged and place them at the tip of the branch you're merging into.
It is called so because, in the 3-way merge, Git uses three commits to generate the merge commit; two branch tips and their common ancestor. Typically, the fast forward merge is used by developers for small features or bug fixes while the 3-way merge is reserved for integrating longer-running features.
Looks like GitHub does not support this – and this is a TERRIBLE affair. You basically CANNOT run an atomic, linear commit strategy (the best there is) using the GitHub UI.
Note that Bitbucket DOES support this, and has much more fine-grained options for setting up the PR landing/integration strategy. Namely the 'Rebase, fast-forward' option which does a --ff-only
update of the target/mainline branch. It also has a 'Rebase, merge' option which lets you run a rebase on target (so that your commits are linear) but integrates using a merge commit (if you want to track that the commits are all part of one logical unit/PR).
Both of these options seem superior to GitHub's limited options of either using non-linear merge commits (GitHub's 'Merge pull request' option) or linear rebase ('Rebase and merge' option), which does achieve linearity but creates duplicate commits on the source branch, thus always requiring manual Hard Resets locally if you want to keep things clean and in sync.
So... time to switch your repo provider it seems!
Based on GitHub's documentation and my own testing, it is not possible to do a fast-forward with the same commit hash.
The rebase and merge behavior on GitHub deviates slightly from git rebase. Rebase and merge on GitHub will always update the committer information and create new commit SHAs, whereas git rebase outside of GitHub does not change the committer information when the rebase happens on top of an ancestor commit. For more information about git rebase, see the "Git rebase" chapter from the Pro Git book.
https://docs.github.com/en/github/administering-a-repository/about-merge-methods-on-github
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With