How do I flatten this so that my git main branch is a nice straight line of commits?

69 views Asked by At

enter image description here

This is my current git. And now when i try to change commit messages in the past (before the git merge), i think it's impossible because of this merge request in the middle.

How do I straighten this without losing the granular commits in the history?

I have googled and found answers about git merge squashing but they sound scary and without visuals, I dare not experiment for fear of losing my history.

2

There are 2 answers

2
William Pursell On BEST ANSWER

There is undoubtedly some cleaner way to do this, but the basic idea is that you want to work with the commits just before the merge and rebase appropriately. But the commits after the merge-point are a bit of a pain. If there are no merge conflicts, this can be fairly painless. If there are any merge conflicts, you will probably have to resolve each manually and it may be frustrating. For example:

$ git log --pretty=oneline --graph
* 81937bf8927254d3167e4f539b302bf98096979a (HEAD -> main) Commit f in main
* e11e3722c40ebfa548cbfcb8865747b9af1d1f2d Commit e in main
* 958376f8c38b2ca0e095e56bf5b5ce4ff54bfa0d Commit d in main
*   a6f098f5cb0516460e79578176bb57cb43084e9e Merge branch 'green_deploy'
|\  
| * 0f0010e7b33e36bc6b66aa8d3ebdc9c1a9ac4cde Add text in green deploy
* | 4d2b2e1a38cd71173321c6add56abf8a822b1257 Commit c in main
* | 57d48c7a48407bed1e996c815f7707a8c4381867 Commit b in main
* | f3277f790acab908de318fbb41fa267a52ff1305 Commit a in main
|/  
* 01e267fb13bf5107f1d5f5fa49400222231422c4 Add file
$ M=a6f098f5
$ g branch merge-point $M
$ git branch tmp ${M}^2
$ git branch orig # Not strictly necessary, but a good sanity check for recovery
$ git reset --hard ${M}^1     # CAUTION
HEAD is now at 4d2b2e1 Commit c in main
$ git rev-list merge-point..orig --reverse | xargs -n 1 git cherry-pick
[main b7b179a] Commit d in main
 Date: Sat Aug 19 07:18:53 2023 -0600
 1 file changed, 1 insertion(+)
[main 58c0280] Commit e in main
 Date: Sat Aug 19 07:18:53 2023 -0600
 1 file changed, 1 insertion(+)
[main 463eb2a] Commit f in main
 Date: Sat Aug 19 07:18:54 2023 -0600
 1 file changed, 1 insertion(+)
$ git cherry-pick tmp
[main 62ecaf8] Add text in green deploy
 Date: Sat Aug 19 07:00:21 2023 -0600
 1 file changed, 1 insertion(+), 1 deletion(-)
$ git log --pretty=oneline --graph
* 62ecaf8b635f86d55c8103aa00ef2bd894fcb8ad (HEAD -> main) Add text in green deploy
* 463eb2a233b7bb0ac3e7f0fd3ee6de027a300650 Commit f in main
* 58c02806727bdf534adb9c338e506cdffcfea96c Commit e in main
* b7b179ad2ec4cd3048707b9150ccfe378cc2df45 Commit d in main
* 4d2b2e1a38cd71173321c6add56abf8a822b1257 Commit c in main
* 57d48c7a48407bed1e996c815f7707a8c4381867 Commit b in main
* f3277f790acab908de318fbb41fa267a52ff1305 Commit a in main
* 01e267fb13bf5107f1d5f5fa49400222231422c4 Add file

Disclaimer: although commits are immutable and it is genuinely difficult to actually lose any data with git, git reset --hard does modify the working directory. If there are changes in the working directory that are not committed, git reset --hard will cause those changes to be lost. Consider yourself warned. In short, if you blindly follow the above commands without making an effort to understand what they are doing, it is your own fault if you cause yourself trouble.

Also note that I'm cherry-picking all of the commits rather than rebasing, but the principal is the same.

0
LeGEC On

Run git rebase <commit-id>, where <commit-id> is the fork point -- in your case, the commit with subject :

fix: pytest to work with ...