Given that I have a commit like the following:
A - B - C - D - G - H \ / - E - F -
How do I get a perfectly linear history following only the first parents?
Eg, I want to get:
A - B - C - D - G'- H'
It is expected that the sha1's of G and H will change, as noted above. (For obvious reasons). If the sha1's for A, B, C, and D change as well, then I want to know why.
The intention is to avoid potential merge commits that would arise when doing a naive git rebase -i.
The real point is to hopefully gain additional insight in order to determine which commits are in a particular branch, eg, if we have the following graph:
I - J - K - L - M \ / / / - N - O - P -
Where N was merged into K, but O was merged with --strategy=ours into L, and P was merged into M.
I want to be able to linearlize my history so that such problematic commits can be identified, and inspected. I want to have a tree where can identify that O was not put into the upstream branch, even if I potentially identify N and P as being potentially missing from the upstream branch as well, by using git cherry, however any suggestions here would be appreciated.
A linear history is simply a Git history in which all commits come after one another. I.e. you will not find any merges of branches with independent commit histories.
Avoid [merge --no-ff] So GIT will create a linear history without creating a "new merge commit", just by mixing and move HEAD pointer. 👉 This case can change, it depends on: Is the target branch ahead (more changes) ? Gitlab/Github merges configuration (default --no-ff ? )
No extraneous commits in history. Splitting branches/PR's into smaller chunks for easier review, and testing is easier without merge commits. Being able to rebase feature branches easily (Fx. to change merge order) It encourages meaningful commit messages (but does not enforce it)
As you said, the following command works:
git filter-branch --parent-filter 'cut -f 2,3 -d " "'
Why?
The problem you pose is solved by transforming each merge commit with a simple commit: this will simply remove the feature branches that were merged, since they will become orphan.
Each commit has one or more parent commits. Merge commit are the one which get more than one. Git stores this in each commit object of the history.
The git filter-branch
command, with the --parent-filter
option, allows to rewrite every commit's parent, passed to the filter as -p SHA1
, repeated if there are more than one parent. Our filter cuts the parent and forces every commit to have a single parent.
For bonus, here's how to do it manually on a precise commit, by re-creating a new commit:
get the commit tree and the first parent
tree=`git show -s --format=%T SHA1` parent=`git show -s --format=%P SHA1 | cut -d " " -f1`
make a new commit with the same tree, same message, and keep only the first parent as ancestor
git show -s --format=%B SHA1 | git commit-tree $tree -p $parent
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