35

I have a project with a dev branch and a production branch. Recently I've been working on a big new set of features in dev, so I haven't merged into production for about two weeks. In the meantime, though, there were some bugs that needed to be fixed in production.

For the most part I was able to make the fixes in dev and cherry-pick them into production. Sometimes, however, I would need to fix production by hand, as the fixes were substantially different in the two branches. Point is, the two branches have diverged a fair bit since they split.

Now I want to just push all of dev into production. I don't care about keeping any of the commits in production since the split, I just want production to look exactly like dev. [EDIT: I want production to look exactly like dev since the split, but don't want to rewrite history before the split] However, when I try to merge I get dozens of conflicts that I'd prefer not to fix by hand.

What's the best way to force a merge in git? Can I revert my production changes back to the split and then just fast-forward to the dev branch?

user2248727
  • 437
  • 1
  • 4
  • 16
Sam Fen
  • 5,074
  • 5
  • 30
  • 56

2 Answers2

29

You can just push your dev branch onto the master repo production branch:

git push --force upstream-remote dev:production

upstream-remote may just be origin if you're on a default clone.

Updated for mod'ed question:

You probably don't want to revert in the git sense but, yes, that's more or less what you want to do. Something like

git checkout -b merge <split hash>
git merge dev
git push --force origin merge:production

<split hash> was the last commit on production that you want to keep.

smparkes
  • 13,807
  • 4
  • 36
  • 61
  • Hmmm, actually I think I misspoke when I said I wanted "production to look exactly like dev." What I meant was that I wanted the branch to look exactly like dev *since the split*. That is, I want to have all the dev commits since the split applied to production, without caring about the production commits. However, I don't want to rewrite history *before* the split, which it sounds like your solution would do. – Sam Fen Feb 24 '12 at 17:19
  • 1
    The two branches were the same at the split? That's what it sounds like. If so, they had the same history prior to the split and so you don't lose anything. – smparkes Feb 24 '12 at 17:24
  • The branch history wasn't the same. I guess I keep misspeaking. Two weeks ago the files were all identical, and I had just merged from dev into production cleanly. After that they started to diverge -- that's what I was calling the split. But the history of the two branches is different. – Sam Fen Feb 24 '12 at 17:27
  • 2
    BTW, FWIW, keeping a `dev` branch that has a history different from `production` is something of an anti-pattern. Better to ditch any feature branches after the `production` merge and create new ones from the new `production` head. – smparkes Feb 24 '12 at 17:39
  • Sweet, your updated answer was exactly what I was looking for. Thanks! – Sam Fen Feb 24 '12 at 17:43
  • Excellent answer. Tried -X theirs, etc. None worked, still had merge conflicts. This worked like a charm – braden Mar 11 '15 at 19:33
  • how do you merge it locally without having to manually pass the vim commit message with , ESC :wq – SuperUberDuper Nov 09 '16 at 13:18
-4

This will merge your newBranch in existing baseBranch

git checkout <baseBranch> // checkout baseBranch
git merge -s ours <newBranch> // this will simply merge newBranch in baseBranch
git rm -rf . 
git checkout newBranch -- . 
Pawan Maheshwari
  • 15,088
  • 1
  • 48
  • 50
  • The reader should note `-s ours` will overwrite existing work while `-X ours` will allow non-conflicting differences to merge. `-s ours` will make a branch have the same state as another, while `-X our` does not simply clobber a branch. I'm not correcting the proposed answer but pointing out an important detail. – haleonj Nov 17 '15 at 14:46
  • This feels like an answer that would be good to resurrect. I have used `git merge -s ours ` twice myself now, and it appears to do exactly what I want. Unlike a force-push, it maintains a version history. Note: I do merge the into the new branch, not the other way around. – Josiah Yoder May 19 '20 at 15:45
  • I think the better form is `git checkout ; git merge -s ours ` followed by a pull request from newBranch into oldBranch. This replaces everything in oldBranch with the current contents of newBranch. It does this by recording a merge of oldBranch into the newBranch **without actually changing anything in newBranch**. But because the oldBranch is there in the merge history, the pull request from newBranch into oldBranch is considered a fast-forward merge. – Josiah Yoder May 19 '20 at 15:55
  • Then the `git rm -rf .` and `git checkout newBranch -- .` aren't needed at all. – Josiah Yoder May 19 '20 at 15:56
  • There is one condition under which I know `git merge -s ours ` fails: That is when the newBranch is directly downstream from the oldBranch. (Or was it the other way around?) I think some sort of fast forwarding can resolve this, but I haven't found time to test this theory. – Josiah Yoder May 19 '20 at 16:07