16

I want to selectively promote a number of commits from one branch to another with a PR review.

Imagine I have on my master branch the following commits:

8b08096 - mod4 97eff67 - mod3 b64891f - mod2 fa6e804 - mod1 956e388 - initial 

On my staging branch I have only the following:

956e388 - initial 

I now want to "promote" the commits for mod1, mod2 & mod3 from master to the staging branch. So, from staging I create a new temporary branch and merge the commits up until mod3:

git checkout staging git checkout -b promote git merge 97eff67 

Doing a git log now shows me all the commits including mod3 on my promote branch:

git log --pretty=oneline 97eff67 (HEAD -> promote) mod3 b64891f mod2 fa6e804 mod1 956e388 (origin/staging, staging) initial git push origin promote 

I can now create my PR for the team to review the changes.

However, when it comes to merging this into the staging branch, GitHub gives me 3 options; Merge, Squash & Merge and Rebase & Merge. I don't want to do Merge since that gives me a merge commit. I don't want to do Squash & Merge since that will squash all my commits into a single commit so I'm left with Rebase & Merge.

When I do a Rebase & Merge, all the changes are applied to the staging branch. However, all the commits have now been given new hashes (except of course for the "initial" commit):

2d7177a - mod3 2831f46 - mod2 a8a2e15 - mod1 956e388 - initial 

How can I merge the commits from my promote branch into my staging branch while keeping the commit hashes intact?

2
  • 1
    It seems they should give a rebase option when the commit history allows a clean rebase. If you don't absolutely need the GH PR, you could rebase manually :/ Commented Aug 22, 2021 at 4:47
  • 2
    @JScoobyCed Or they could just automatically copy the commits when possible during a rebase instead of always replacing them. If I have tags on my commits or I've GPG-signed my commits, GitHub's broken rebase option always orphans those tags and signed commits so they're only on my PR branch without going into main. The only way to get GitHub to copy your commits as-is (preserving the commit hash so the GPG-signing and tags remain) is to use the merge-commit option that adds a redundant commit. Commented Dec 31, 2021 at 21:03

1 Answer 1

16

That's perfectly normal:1 rebase copies commits to new and (supposedly) improved commits, which means they will have different hash IDs.

How can I merge the commits from my promote branch into my staging branch while keeping the commit hashes intact?

Do not use REBASE AND MERGE.

GitHub do not provide a button that would do what I wish they allowed. This means that if you wish to merge a branch on GitHub, you must use the MERGE button.

To merge without a "merge bubble" (i.e., sans merge commit) as a fast-forward instead, you will have to do the fast-forward on your own machine, and then use git push to send the updated commit hash ID to GitHub. That is:

git fetch 

(so that you have everything on your laptop or wherever—this step is often unnecessary, but never hurts), then:

git checkout staging git merge --ff-only origin/staging # if needed git merge --ff-only origin/promote # whatever fast forward you want here git push origin staging 

The checkout-and-fast-forward for staging is only needed if your own staging is behind origin/staging after the git fetch step. The git merge --ff-only commands achieve the fast-forward-instead-of-merge operation.


1Normal for GitHub, anyway. Some systems allow a fast-forward merge operation here, where this would not occur. GitHub is not one of these. REBASE AND MERGE does a forced rebase, making it "normal".

Sign up to request clarification or add additional context in comments.

6 Comments

As for the "[Github] copies commits to new and (supposedly) improved commits", I wonder why they think the commits are improved. I chatted with support, but they had no reason.
@Garrett: they have a different committer field (as configured by whoever is doing the rebase) and time-stamp. Not much of an improvement, as far as I'm concerned. They may also have different parent hash IDs, in which case the copying is forced, but they may not, in which case I just find it annoying.
@torek I would say it's not "perfectly normal", since gitlab for instance does it differently and allows to not change any commit-hash when doing a fast-forward merge. This github feature is quite broken in my opinion. The "rebase and merge" is doing the equivalent of "git rebase --force" in the background, instead of doing a simple "git rebase" which would be a NO-OP for a fast-forward merge.
@Étienne: I've added a footnote. It's normal for GitHub because GitHub are annoying. :-) Note that GitLab's action here is what I meant by "GitHub do not provide a button that would do what I wish they allowed".
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.