Question

I need to revert a whole branch with a single commit like this:

          [topic]
     o---o---o-------X
    /
   |      [master]
---o---o---o

The commit X must have state like a master~2 (the origin point of topic branch)

My solution is:

git rev-list --reverse master..topic | while read SHA; do
   git revert -n ${SHA}
done
git commit -m "Reverted topic branch"

Is there a better (shorter) solution?

A PURPOSE OF THIS

Imagine I have a kind of almost-git-flow based repo.

              [release-3]
       o---o---o---o
      /         \       [fix-for-rc-3]
     /           o---o---o
    /
   |      [development]
---o---o---o

I have a development branch, upcoming release-3 branch and a so-called hot-fix-feature-for-rc-3 branch. In this branch I'm doing some ugly hack to get my release done but I don't want it in a development at all because more "correct" solution is already landed here but can't be applied to a release-3 branch by some reason. So, I must do the following...

                                    [release-3]
       o---o---o---o--------------------M
      /         \       [fix-for-rc-3] /
     /           o---o---o----------------X
    /                                      \
   |                                        \[development]
---o---o---o---------------------------------D

I must merge fix-for-rc-3 to a release-3 (point M), then do a "revert-all-this-shit" commit (point X) and merge it do development (point D) so this code will never get here, even then a whole release-3 branch is merged to development then release is done.

That's why I need to revert a whole branch...

THE PROBLEM

While the root issue is solved, there are still problem getting fork point of a branch cause' if topic is already merged to release merge-base will fail.

Was it helpful?

Solution

You can create a commit that reverts to the base of the branch like this:

# on "topic" branch
git read-tree $(git merge-base topic master)
git commit -m "Reverted topic branch"
git checkout -- . # update working copy to match the committed tree

In your example use, you want to revert the changes so that you can merge the branch back into master (or development as it's called in your example) without actually incorporating any of the changes from the topic branch. But that can be done without adding a revert commit by using the "ours" merge strategy. From the git-merge documentation:

ours

This resolves any number of heads, but the resulting tree of the merge is always that of the current branch head, effectively ignoring all changes from all other branches. It is meant to be used to supersede old development history of side branches. Note that this is different from the -Xours option to the recursive merge strategy.

For example:

git checkout master
git merge -s ours topic

OTHER TIPS

You can read the tree information of the commit into the index and then commit the index. That way, your new commit will have the exact same tree state as the old one.

git checkout topic
git read-tree master~2
git commit -m 'revert complete branch'

May I ask why you are doing this? What problem are you trying to solve? What's the purpose of having a branch that is then reverted completely?

What is about "merge" with "ours" strategy?

$ git checkout master~2
......
HEAD is now at 06a96da... c2
$ git merge -s ours topic 
Merge made by the 'ours' strategy.
kan@altegol:/tmp/g$ git checkout topic 
Warning: you are leaving 1 commit behind, not connected to
any of your branches:

  cdaad73 Merge branch 'topic' into HEAD
....
Switched to branch 'topic'
$ git merge cdaad73
Updating 0b980be..cdaad73
Fast-forward

In comparison to another solutions this solution is better as it creates merge commit which explicitly shows exact history which points to the commit to which you are reverting to.

I don't know, if I get this right, but shouldn't it be simply that?

git checkout topic
git reset --hard master~2
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top