DEV Community

Josef Andersson
Josef Andersson

Posted on

The "linear git commit history with signing in GitHub-UI"-workaround

Intro

I prefer maintaining a linear Git history, where features are added in traceable portions. This approach has many benefits, as it makes it easy to track what has happened earlier in the project. Such a workflow often necessitates the frequent use of Git rebase capabilities, including:

  • Rebasing the feature branch into a coherent feature chunk.
  • Rebasing it against the main branch to keep it on top of other changes.
  • And so on.

Another Git/Git-service feature I appreciate is the ability to sign commits, which UI-wise results in a green "Verified" label on the Git-service's UI. This adds an extra layer of trust regarding the identity of the commit/feature submitter.

Every major Git service provider, including GitLab, BitBucket, and GitHub, supports this workflow. Or do they?

The Problem:

To be honest, GitHub has a issue in this regard. In short, when performing a rebase action in the GitHub UI, it will rewrite your commits, even if the feature branch could be merged without merge commits. This means you will lose your signed verification signature — quite a horror!

Note, Other major platforms will perform the expected fast-forward-only merge in the same case, meaning they won't create any merge commits. This allows you to simply add the commit on top of the main branch, preserving the signature.

This is a known GitHub-problem, as evidenced by discussions at GitHub Community and Stack Overflow.

GitHub has also acknowledged this issue with their platform. It is highlighted in their documentation and has received a response from their support:

This is a known issue we are tracking internally and a pain point for a number of folks....

Currently, reverted pull requests created from a previously squash and merge pull request or a rebase and merge pull request are indeed not signed...

While we don’t yet have a specific ETA for when this might be implemented...

Pain point?! YES!

The Workaround:

So, what can you do? Just follow their advice in their documentation: "A workaround for this is to rebase and merge locally, and then push the changes to the pull request's base branch." Aha, seems easy in words, but how can you translate this into terminal commands?

For example, if you have a pull request that you are ready to merge:

First, fetch the pull request locally by creating a feature branch for it.

git fetch origin pull/<PULL-REQUEST-NUMBER>/head:<NAME-YOU-WANT-THE-PR-BRANCH-TO-HAVE-LOCALLY>
Enter fullscreen mode Exit fullscreen mode

Then, while on your base branch i.e main, merge the locally fetched PR branch into it.

git merge --ff-only <THE-LOCAL-PR-BRANCH>
Enter fullscreen mode Exit fullscreen mode

Finally, push it to the base branch.

git push
Enter fullscreen mode Exit fullscreen mode

GitHub will now close the pull request as merged, and you will have a clean commit history with the signed commit intact.

The Summary:

Is pushing to the main branch a hackish? Yes, but until GitHub fixes this problem, it is the only way and they recommend it in the documentation.

Other

Other Git related articles on DEV from me:
Git signing and signoff like a champ
A clean Git history with Git Rebase and Conventional Commits

Top comments (2)

Collapse
 
ericherman profile image
Eric Herman • Edited

I too would rather avoid complicated graphs in my git histories. However, I see value in the merge commits as they very clearly show the "two brains" principle, and retain context for sets of commits.

Here is a sample for the Standard for Public Code:

$ git log --pretty=format:'%h %s [%an]' --graph
*   6355a43 Merge pull request #988 from publiccodenet/ignore-bundle-config-dir [Jan Ainali]
|\  
| * 4c6d876 ignore `.bundle/` directory [Eric Herman]
|/  
*   ec97922 Merge pull request #987 from publiccodenet/mdl-0.13-ignore-table [Jan Ainali]
|\  
| * 50a975d Ignore mdl 0.13 table strictness [Eric Herman]
|/  
*   e4e4e18 Merge pull request #984 from publiccodenet/update-roadmap [Eric Herman]
|\  
| * 1fb60f5 Add multiple versions to roadmap [Ainali]
| * f9c4e3d Remove physical checklist from roadmap [Ainali]
| * 1fa252d Remove certification badges from roadmap [Ainali]
|/  
*   101dd8c Merge pull request #982 from publiccodenet/machine-readable-20230919T142903Z [Jan Ainali]
Enter fullscreen mode Exit fullscreen mode

In the above, it can easily be seen that for each contribution one person created a change and another person reviewed and merged it.

Also the logical grouping of sets of commits are retained, as in the case of the 3 roadmap related commits by Ainali.

While not perfectly linear (as long as there is a rebase before merge) the commit history remains easy to understand and remains linear from a git bisect perspective.

Collapse
 
janderssonse profile image
Josef Andersson • Edited

I'm a bit boring here in my answer as I must say I agree here Eric. Merge commits has it's merits, and it's easy to skip them if the need arises for autogeneration of Changelogs etc. Like much things in our development sphere is comes down to developer or team tastes at times. The important thing is that the project has some agreement as how they want it, it and then it is not as important as how what they want is achieved.