Reputation: 333
The problem: A branch has good commits interleaved with undesired ones.
Attempted solution:
git revert hash5 hash8 hash9 hash23
What I thought this would do is that it'd apply all specified commits, and then let me sort out any conflicts.
What I now think that happens:
Question: How do I get git to apply all the reverts in a row before presenting any possible conflicts to me?
Upvotes: 17
Views: 3714
Reputation: 11952
First, note that git revert
reverts your patches in the order you list their hashes; you need to list the hashes from newest to oldest, since you want to proceed backwards in time. So, I'm going to call your hashes
<hash1> ... <hashN>
where <hash1>
is older than <hash2>
... is older than <hashN>
. So, make sure you were doing
git revert <hashN> ... <hash1>
in the first place!
Second, assuming you had been reverting them in the right order, try the --no-commit
option:
git revert --no-commit <hashN> ... <hash1>
Third, If the easy solution doesn't work well, but the commits you want to revert really do make sense as a single commit (if not I don't see much hope), then try this: build one big commit out of the four you want to revert, and then revert the big commit.
Build the big commit:
Create a branch at the parent of the oldest commit:
git checkout -b big-commit <hash1>~
Copy the commits on your new branch and collapse them:
git cherry-pick --no-commit <hash1> ... <hashN>
git commit -m "Big commit"
You should now have one big commit on your branch big-commit
.
Apply the big commit in reverse to the branch you're trying to revert:
git checkout <branch you wanted to revert on>
git revert big-commit
Use selective rebasing to rebuild the branch in question as if it never contained the unwanted commits:
Create a new rebuild
branch to work in:
git checkout -b rebuild <branch you want to revert>
Interactively rebase, dropping the commits you don't want:
git rebase -i <hash1>~
In the interactive rebase editor, delete the lines for <hash1>
... <hashN>
.
Now your rebuild
branch will contain <branch you want to revert>
, as though <hash1>
... <hashN>
never existed. If you run into conflicts here it would seem they're unavoidable.
If you need your work to be on <branch you want to revert>
, and you can't just git reset
it to point to your new rebuild
branch:
git checkout <branch you want to revert>
git reset --hard rebuild
(e.g. because you've already pushed it publicly), then you can instead apply the differences to <branch you want to revert>
as a patch:
git co <branch you want to revert>
git diff <branch you want to revert> rebuild | patch
Upvotes: 12