1

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?

mkrieger1
  • 19,194
  • 5
  • 54
  • 65
Ark-kun
  • 6,358
  • 2
  • 34
  • 70
  • 3
    Any change to a commit results in a new, different commit. If you're OK with that, look into filter-branch and/or filter-repo, which give you direct control over all the parts of each new commit as you completely rewrite everything from that point onward. You'll have to get everyone who has a clone of the original repository to discard *their* clone too, and switch to the new repository. – torek Jul 16 '21 at 06:10

2 Answers2

1

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.

VonC
  • 1,262,500
  • 529
  • 4,410
  • 5,250
  • Interesting. Unfortunately, it does not seem to work for me even in expanded form (where I'm setting all 6 variables). As soon as the rebases reaches the skipped commit, I get `Committer identity unknown *** Please tell me who you are.`. The exec syntax looks strange to be. Are you sure that the quotes are correct? Shouldn't it be `-x 'export GIT_AUTHOR_NAME=$(git show -s --format=%an $(git rev-parse HEAD))'` ? – Ark-kun Jul 17 '21 at 05:42
  • I suspect that even with export, the environment variables are not getting to GIT. – Ark-kun Jul 17 '21 at 08:22
0

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
Ark-kun
  • 6,358
  • 2
  • 34
  • 70