admin管理员组

文章数量:1391937

We had a regression that we can't exactly pinpoint. To get some analysis going we decided to create a new branch master' from current master that is split from master at commit B and it contains all the commits from master except a commit range that we suspect of being the culprit.

A---B---C-...-W---X---Y (master)       
     \                        
      X'---Y' (master')

In this example C-...-W is the suspected commit range that we try to exclude in the mirrored master. How can I do this efficiently?

I tried to do

git checkout -b master-tick B
git revert C^..W

But this works horribly, creating a merge conflict on every iteration (it walks back from W to C). It would be much more preferable for me to reconstruct the master branch from commit B onwards in master'.

We had a regression that we can't exactly pinpoint. To get some analysis going we decided to create a new branch master' from current master that is split from master at commit B and it contains all the commits from master except a commit range that we suspect of being the culprit.

A---B---C-...-W---X---Y (master)       
     \                        
      X'---Y' (master')

In this example C-...-W is the suspected commit range that we try to exclude in the mirrored master. How can I do this efficiently?

I tried to do

git checkout -b master-tick B
git revert C^..W

But this works horribly, creating a merge conflict on every iteration (it walks back from W to C). It would be much more preferable for me to reconstruct the master branch from commit B onwards in master'.

Share Improve this question edited Mar 12 at 15:55 mkrieger1 23.5k7 gold badges64 silver badges82 bronze badges asked Mar 12 at 13:57 gladesglades 4,9882 gold badges22 silver badges64 bronze badges 3
  • 3 Are you aware that git bisect exists? Have you tried to use it? It could solve your original problem more efficiently. – mkrieger1 Commented Mar 12 at 14:27
  • I'm aware of bisect, but it doesn't work in our case i suppose because we're using this in a submodule that the main app relies on. I can't figure out how I would bisect synchronously both repos at the same time. – glades Commented Mar 12 at 14:31
  • To remove earlier commits which are not a contiguous range, interactive rebase will be more practical, see e.g. stackoverflow/questions/17673771/… – mkrieger1 Commented Mar 12 at 15:58
Add a comment  | 

2 Answers 2

Reset to default 3

The problem can be rephrased as: Create a mirror of a branch, containing the latest commits, but based on an earlier commit.

This, quite literally, can be done by using these commands:

git checkout -b master-tick master
git rebase --onto B W

This rebase creates a copy of all commits since W until HEAD, but based on B instead of W, and updates the new master-tick branch label (keeping the original master untouched).

Note that your suggestion:

git checkout -b master-tick B
git revert C^..W

is undoing changes from the commits you don't want, and mkrieger1's answer does the opposite, which is cherry-picking (or rebasing) only the commits you do want. The reason that answer works better in your particular case, is because presumably there are fewer conflicts to resolve with the rebase than with the reverts. Note this may not always be true in the general case.

Since the goal of the master-tick branch is to enable testing, another alternative for this throwaway branch is to use merges. Compared to rebasing or reverting, this method oftentimes has fewer conflicts, and is guaranteed to have at most the same number of conflicts in the worst case. The trick here is to use two merges where you ignore the first, and take the second:

git checkout -b master-tick B
git merge W -s ours # merge but don't take the changes!
git merge master # or if you prefer: git merge Y

The key here is merge -s ours which brings in the commits without their changes. It's not possible to have conflicts with that merge. The second merge can of course have conflicts, but is limited to a one-time conflict resolution, whereas with reverting or rebasing multiple commits, you can potentially have conflicts at each commit in the worst case.

Note the end state of this answer and the rebase answer should be identical.

本文标签: gitCreate master39 mirror branch that contains all commits from master except a rangeStack Overflow