10

How do I remove all commits by certain author (committed by mistake - such an author should not be visible in the commits history).

I have found some code to rename -

git filter-branch --env-filter '
OLD_EMAIL="old@gmail.com"
CORRECT_NAME="name"
CORRECT_EMAIL="new@gmail.com"
if [ "$GIT_COMMITTER_EMAIL" = "$OLD_EMAIL" ]
then
export GIT_COMMITTER_NAME="$CORRECT_NAME"
export GIT_COMMITTER_EMAIL="$CORRECT_EMAIL"
fi
if [ "$GIT_AUTHOR_EMAIL" = "$OLD_EMAIL" ]
then
export GIT_AUTHOR_NAME="$CORRECT_NAME"
export GIT_AUTHOR_EMAIL="$CORRECT_EMAIL"
fi
' --tag-name-filter cat -- --branches --tags


git push --force --tags origin 'refs/heads/*'

Is there some filter not to rename but remove such commits?

Dancyg
  • 139
  • 1
  • 15
  • What do you mean "remove commits"? Does that mean to `rebase` the next commit onto the previous one? Should the changes from the removed commit be kept or rolled back? – Cory Kramer Aug 30 '16 at 16:36
  • All changes from such commits should be removed as well. After these commits some more commits were made. – Dancyg Aug 30 '16 at 16:41

2 Answers2

10

You can do it like this:

  1. Create a new branch based on the commit you want to start with:

    git checkout -b <branch-name> <base-commit>
    
  2. Cherry-pick all commits that don’t have the matching author:

    git log --author "<name>" --invert-grep --reverse --format="format:%H" HEAD..master | xargs git cherry-pick
    

The log filters out all commits made by the author and then cherry-picks them one after one.

Explanation for the parameters (partly quoted from git log manpage):

  • --author "name"
    Limit the commits output to ones with author/committer header lines that match the specified pattern (regular expression). With more than one --author=, commits whose author matches any of the given patterns are chosen (similarly for multiple --committer=).
  • --invert-grep
    Limit the commits output to ones with log message that do not match the pattern specified with --grep=
  • --reverse Output the commits in reverse order. […]
  • --format="format:%H" Use a custom format, in this case only the commit hash
Andreas Wolf
  • 995
  • 6
  • 19
  • It seems that git bash uses author for commits that was last to commit anything but not the logged in one. So i renamed successfully commits that were committed under wrong author. After that my colleagues committed theirs versions that contained wrong author of that bloody commits.) And there doubled commits appeared - identical but with diff authors) But problem was solved when I renamed bad commits ones more - they just disappeared and only those with correct author left) – Dancyg Sep 09 '16 at 08:52
  • @Dancyg usually Git uses the author that is configured in .gitconfig, either the one for the local repo (.git/config), the user or system-wide file (in that order). You can check the configured value with `git config --get-regexp "user.*"`. – Andreas Wolf Sep 11 '16 at 16:32
  • Hopefully this saves someone else time: `main` is probably the branch you want to use in the command now is it is the default rather than master on github You need `...` rather than `..` in your command Also `--author --invert-grep` no longer works; https://stackoverflow.com/questions/6889830/equivalence-of-git-log-exclude-author/70644305#70644305 Try instead ```git log --perl-regexp --author='^((?!).*)$' --reverse --format="format:%H" HEAD...main | xargs git cherry-pick``` – pdewilde Feb 22 '23 at 20:36
0

You can do it directly with a filter-branch. What you can do is to create a new branch with the desired start point and then using filter branch do a cherry-pick to the desired commit leaving out the unwanted ones.

Then in your new branch you will have all the commits without the ones made by a given author.

git cherry-pick support a range so you can save the last "good" commit and than add a range of commits instead of a single one.

Another way is to do a git revert but revert will leave the original commits in place and will just undo the changes made under the original commit.

CodeWizard
  • 128,036
  • 21
  • 144
  • 167