I know how to manually split a commit using git rebase -i
, but how can I automatically split every commit in a branch by file?
For instance, commit A
modified 3 files, f1, f2 and f3. After the split, there are 3 commits A-f1, A-f2 and A-f3.
I want to do this to make a major rewriting easier as I will only have to squash some small commits.
The following script splits HEAD
by file:
#!/usr/bin/env bash
set -e
SHA=$(git rev-parse --short HEAD)
# Change to repo root directory
cd $(git rev-parse --show-toplevel)
git reset HEAD^
git diff-tree --no-commit-id --name-only -r $SHA | while read -r f; do
git add "$f"
GIT_EDITOR="echo '0a\n$SHA $f\n\n.\nw' | ed -s" git commit -c $SHA
done
The generated commit messages are of the form:
<original SHA> <file name>
<original commit message>
The following assumes that you can run above script as git-split
.
If you want to split all commits in a range by file, use it like this:
git rebase --interactive --exec git-split <branch>
If you want to split a single commit during an interactive rebase, use it like this:
p Commit to split
x git-split
Any improvements to the script are welcome.
For every commit, you would need
first to list all files in that commit
git diff-tree --no-commit-id --name-only -r <SHA1>
then for each file, extract that file
git show <SHA1>:/path/within/repo/to/file
Do that in a working tree of a dedicated branch, and for every file extracted, add and commit.
Then you can reset your current branch by that new one built commit-file by commit-file.
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