This gist shows how you can linearize complex Git tree that has many merge commits, making it like a "squash on merge" policy was used from the beginning of repo's history, while modifying commits' authorship in a standardised way.
It checks if a commit is a merge commit and, if so, modifies its author and parents:
- merge commit becomes "regular" commit with only 1 parent
- authorship for ex-merge commit is taken from the last commit of merged branch (2nd parent that is discarded). It assumes that single person was working on a branch, so it may produce false blame information if multiple people authored commits in a branch (all changes from the branch have authorship from last commit's author). In our case it was needed because merge commits are automated and authorship comes from bot user, so without this little hack blame would always show the bot as author of any line.
The main idea of this script is reducing Git repository's tree size, which leads to faster clones (and other Git operations).
Usage: place both file in the root of your repository and run ./linearize_git_history.sh
(don't forget chmod +x
).
Note
Requires git-filter-repo
Warning
DESTRUCTIVE OPERATION! It rewrites Git history, use at your own risk if you know what you're doing.
Let's consider example repository with such a tree:
* a7eed66b - Merge D - Greg (HEAD -> main)
|\
| * 98331fc7 - D - Jack
|/
* d1202c56 - Merge C - Greg
|\
| * 59acc515 - C plus - Jill
| * 5bf839a3 - C - Jack
|/
* 2ea8ca3f - Merge B - John
|\
| * ab229bb9 - B plus - Greg
| * 8c1275ea - B - Greg
|/
* 36c97e8b - Initial commit - Greg
The goal of this script is:
- commit
2ea8ca3f
“Merge B” takes authorship from commitab229bb9
(overrides John with Greg) - commit
d1202c56
“Merge C” takes authorship from commit59acc515
(overrides Greg with Jill) - commit
a7eed66b
“Merge D” takes authorship from commit98331fc7
(overrides Greg with Jack)
Ultimately, resulting repository should look like:
* ???????? - Merge D - Jack (HEAD -> main)
* ???????? - Merge C - Jill
* ???????? - Merge B - Greg Korba
* ???????? - Initial commit - Greg Korba