2

I have a git project and the stable version was always stored in master branch. For a while I was working on version 2.0 in a separate branch v20.

Now I decided to release it and copy everything to master branch again. I don't want to merge it, as there were hundreds of conflicting changes and a lot of files requires manual intervention.

All I want just to make a snapshot of v20 branch and put it to master without affecting the old history, without rebase (so other users won't be affected as well). Just to make it look like there was just a new commit which brings all the changes.

Start state:

 master branch --------- v20 branch
       |                     |
 master files ---------  v20 files
       |                     |
master_history          v20_history

Target state:

 master branch --------- v20 branch
       |                     |
   v20 files   --------  v20 files
       |                     |
master_history          v20_history
+ commit from v20

Is there an existing git way to do that?

rush
  • 2,484
  • 2
  • 19
  • 31
  • @DaveNewton you mean `-s recursive -X theirs`? It doesn't work that way. It still leaves a lot of unresolved conflict which requires manual intervention. It's not a copy. I need exactly the state of my branch but in master. – rush Jul 25 '17 at 23:59
  • 3
    What about (while you are in v20) `merge -s ours master` (not `-s recursive -X ours`), then, merge v20 into master? – mayo Jul 26 '17 at 00:07

1 Answers1

4

You are describing the result of git merge -s theirs, which does not exist, and one of the main Git authors insists that it should not exist:. Quoting from that link (these are not my words):

Heh, now you have some readings to do ;-)

I tried not to sound too negative when describing -Xours and -Xtheirs there, but actually I think "-s theirs" is even worse. It is how you would discard what you did (perhaps because the other side has much better solution than your hack), but that can be much more easily and cleanly done with:

$ git reset --hard origin

Some people might say "But with 'merge -s theirs', I can keep what I did, too". That reset is simply discarding what I did.

That logic also is flawed. You can instead:

$ git branch i-was-stupid
$ git reset --hard origin

if you really want to keep record of your failure.

One big problem "-s theirs" has, compared to the above "reset to origin, discarding or setting aside the failed history" is that your 'master' history that your further development is based on will keep your failed crap in it forever if you did "-s theirs". Hopefully you will become a better programmer over time, and you may eventually have something worth sharing with the world near the tip of your master branch. When that happens, however, you cannot offer your master branch to be pulled by the upstream, as the wider world will not be interested in your earlier mistakes at all.

You can feel free to disagree with the Git folks and go on and use some of the answers to Is there a "theirs" version of "git merge -s ours"? Note that the accepted answer is not truly a -s theirs at all. Michael R's answer, using git read-tree to switch out the index during a --no-commit merge, is correct.

The method in mayo's comment is also good, and jthill's answer to the other SO question is correct as well.

Your case is a bit different from the one being described above, but really, you can just rename the "bad" branch and rename the "good" branch to master and go on from there. Anyone "downstream" from you will need this same renaming, so there are multiple points to consider.

torek
  • 448,244
  • 59
  • 642
  • 775