I expected this to be as easy as interactive rebase, but I've noticed that rebase changes commit dates and committers.
What would be the easiest way to remove a commit from history while leaving everything else the same?
I expected this to be as easy as interactive rebase, but I've noticed that rebase changes commit dates and committers.
What would be the easiest way to remove a commit from history while leaving everything else the same?
git rebase
has a -x
/--exec
option which can help.
You can add environment variables which will, for each commit in the rebase todo
list, help to keep date/author unchanged:
I mention that in "git rebase without changing commit timestamps"
git rebase -i --committer-date-is-author-date \
-x 'git config user.name "$(git show -s --format=%an $(git rev-parse HEAD))"' \
-x 'git config user.email "$(git show -s --format=%ae $(git rev-parse HEAD))"' \
@~x
(replace x
in @~x
by the number of commits you want your interactive rebase to start)
The problem is: you will need to manually copy those generated lines before the first pick
todo item, in order for the first commit to use those settings.
I've tried multiple approaches using git rebase
and git filter-branch
, but neither worked. git filter-branch
likely cannot work, since it operates on snapshots, while removing commits require operating on change-sets/patches.
The only solution that worked was to create my own rebase based on git cherry-pick
:
# !!! Only do this when the working copy is clean !!!
git checkout --orphan new_branch
# Now clean up all the files
# !!! Careful !!!
# git reset --keep
git log --reverse --format=%H source_branch |
grep -v -E "sha1|sha2|sha3" |
while read sha; do
(
echo "Cherry-picking $(git show --no-patch --format=oneline "$sha")"
export GIT_COMMITTER_NAME=$(git show -s --format=%cn "$sha")
export GIT_COMMITTER_EMAIL=$(git show -s --format=%ce "$sha")
export GIT_COMMITTER_DATE=$(git show -s --format=%cd "$sha")
git cherry-pick "$sha" -Xtheirs
)
done