1

I would like to non-interactively remove unpushed commits containing a subject keyword from my history (similar to interactive rebase where the lines containing the keyword is removed).

The following nocommit function in ~/.gitconfig achieves almost what I want, except that a new resulting branch is created.

nocommit = "!f() { \
    for i in `git log --oneline FETCH_HEAD.. |grep NOCOMMIT | awk '{ print $1 }'`; \
    do \
        git log -n1 --oneline $i; \
        git rebase --onto $i^ $i HEAD; \
    done; \
}; f"

It should also be possible to do this with a git push hook, but we already have in-three hooks in that I don't want to modify.

Edit: Solved with this command (Inspired by the answer from Andrew C):

GIT_EDITOR="sed -i '/NOCOMMIT/d'" git rebase -i @{upstream}
badeip
  • 602
  • 8
  • 9
  • possible duplicate of [Using git filter-branch to remove commits by their commit message](http://stackoverflow.com/questions/4558162/using-git-filter-branch-to-remove-commits-by-their-commit-message) – jub0bs Sep 20 '14 at 16:30
  • I'm afraid this is not guaranteed to be non-interactive. Whenever you remove a commit from history, there's a risk of getting conflicts and those have to be resolved interactively. – Pavel Šimerda Sep 21 '14 at 07:00

1 Answers1

2

A few comments.

You are running through the commits 'backwards', from newest to oldest. The reason rebase runs from oldest to newest is that you only process each commit once.

The first line of your script would probably better be written as

for i in `git rev-list --grep=NOCOMMIT @{u}..HEAD`

Using FETCH_HEAD isn't a good way to limit commits, and having pipes to grep and awk aren't needed.

To make it more rebase like you would have to keep track of ORIG_HEAD, checkout a new branch from git merge-base ORIG_HEAD ${u}, then run through the commits from oldest to newest (--reverse), cherry-picking any that didn't have NOCOMMIT in them, and then update the branch at the end.

Another option would be to trick interactive rebase into doing what you want by saving off your editor setting and replacing it with a script that just deleted lines containing NOCOMMIT. So you would have a normal call to git rebase -i, but instead of getting the editor window sed would just delete the commits you didn't want and it would proceed.

Andrew C
  • 13,845
  • 6
  • 50
  • 57
  • Specifying an alternative editor for rebase -i seems appealing, but for some reason I was not able to get it working: GIT_EDITOR="grep -v NOCOMMIT" git rebase -i HEAD~5 – badeip Sep 20 '14 at 20:42
  • 2
    grep isn't going to save the resulting file. try `sed -i '/NOCOMMIT/d'` – Andrew C Sep 20 '14 at 22:16