As much as I've tried to avoid it, I have to maintain three master
-equivalient branches with minor changes in each one. I've been reading about git
and using it for a couple of years, so I'm familiar with the following conventional wisdom:
merge
unless it is meaningful. Use rebase
instead.cherry-pick
is your friend.pull --rebase
on the remote before pushing.rebase
.What they don't tell you is the conventional wisdom creates a bunch of commits that are nearly identical, except for minor details that change their SHA1s. Why does this matter? It defeats the purpose of comparing branches with git log --left-right --graph --cherry-pick --oneline branch1..branch2
and git show-branch
, which is especially annoying. Feels like an abuse of cheap branching. It makes it nearly impossible to see which patches are missing from each branch.
So, how do you keep multiple branches in line with identical SHA1s so these tools can be used? Are patches the best way to do this?
You cannot keep commits with identical SHAs in multiple places because the "place" of a commit (its location in history) is identified by the SHA.
A Git commit contains certain data, among them a snapshot of the current repo state, the current time and date, the committer name and email, and the SHA of the parent commit(s).
That means that when you put a commit somewhere else (rebase
, cherry-pick
, patch+apply) or change its time (commit --amend
), the SHA will be different.
This is a significant feature of Git (Git history is a so-called Merkle tree).
As you have noticed, you can maintain (content-)equivalent commits by using the various history-rewrite commands I mentioned above.
Depending on your situation, you might be able to use the commits which are in master
without having to copy them. If those changes that make your "master
-equivalent" branches different are purely additive (i.e. they occur in commits which can always be appended to the latest commit in master), then you can just always rebase your other branches onto master
and be happy, because then they simply contain all of master
's commits exactly as they are.
If your changes are, on the other hand, of a kind which requires to be inserted earlier in history (i.e. new commits to master
must be appended after your differentiating changes), then you will not be able to keep a "nice" history like that.
I can't spontaneously think of an example of the second situation, but it's theoretically possible (be it actually required by the content, or required by external factors like project specifications).