1

I have the following bash script:

git merge --squash -Xtheirs dev -m "squashing" && 
(./test/testsrc/shell/node-c.sh && echo "compiled successfully") || (git reset --hard; exit 1)

I have two questions:

  1. If the merge fails, do I need to do a git reset to go back to the state before the merge started?
  2. Assuming the answer to 1 is "yes", is the above script correct, such that if the node-c.sh script exits with a non-zero code, that git reset --hard will be called and will absolutely exit with code = 1?

I am thinking that when running git merge, the index will always be updated no matter what, so that git reset --hard is always the right thing to do.

As an aside, I am seeing what appear to be some bad Git bug, where the merge doesn't work and produces .js files that get mangled, and often times cannot even by compiled with "$ node -c". Not sure if anyone has seen this before, but I have filed a bug report with Git.

Alexander Mills
  • 90,741
  • 139
  • 482
  • 817
  • 2
    _I have filed a bug report_: And you have been told essentially that `-Xtheirs` is not a magic bullet, on the contrary, it is just enough rope... ;-) – j6t Dec 15 '16 at 21:54
  • @j6t you are absolutely right, that's what the Git folks told me :) Maybe that was you haha. TBH with the failure rate that I have seen -Xtheirs should come with more warnings than those that I have / haven't seen. At least when merging JavaScript code. – Alexander Mills Dec 15 '16 at 22:08
  • Rather than `git reset --hard` you should use `git merge --abort`. (They wind up doing the same thing for your case but the `merge --abort` is clearer, and more obviously future-proof). That's for the failed merge part; for the "undo the merge" use `git reset --hard ORIG_HEAD`, as you are doing. – torek Dec 15 '16 at 22:12
  • so I need two commands like so? ... || (git merge --abort && git reset --hard ORIG_HEAD; exit 1) – Alexander Mills Dec 15 '16 at 22:25
  • 1
    @AlexanderMills: as in j6t's answer, you don't *need* it, I'd just recommend it for clarity. But it would be: `if ! git merge ...; then git merge --abort; elif ! script-test; then git reset --hard ORIG_HEAD; else echo total success whee; fi`. More or less. – torek Dec 15 '16 at 22:28

2 Answers2

3

If the merge fails, you're going to be in a conflict state with the branches. My thought on this is that you're going to be safer with using git merge --abort rather than git reset --hard, since:

  • It's clear from the context of the command that you're only aborting the merge, and
  • Things could crop up in Git's stage that would be lost forever due to a merge failure

You don't want to ever hard-reset a branch without some kind of human/manual intervention; even though what you're resetting would likely be safe, you're still playing with plutonium.


As to your Git "bug" - I genuinely doubt that Git is to blame; it could be a side effect from the intended merge not going as planned and Git requiring that you help it along.

Makoto
  • 104,088
  • 27
  • 192
  • 230
1

In your script, you should actually do this:

git merge --squash -Xtheirs dev -m "squashing" && 
(./test/testsrc/shell/node-c.sh && echo "compiled successfully") ||
(git reset --hard ORIG_HEAD; exit 1)

When the merge goes through, but node-c.sh does not, then you have a merge commit that you do not want. The pseudo-ref ORIG_HEAD points to where you were when the most recent merge started: If the merge failed, it is the same as HEAD, and when it was successful, it is the same as HEAD^.

j6t
  • 9,150
  • 1
  • 15
  • 35
  • Doing one `git reset --hard ORIG_HEAD` clearly works, but for future-proofing, I'd suggest doing a separate `git merge --abort` if the merge itself fails. (I'm not aware of any plan to *change* how `git reset --hard` works, but given the existence of `git merge --abort`, it seems like some future `git reset` might start giving you a "merge in progress, abort it first if that's what you meant" error.) – torek Dec 15 '16 at 22:17
  • @torek Git has a record for not breaking compatibility. It is, therefore, very unlikely that `git reset --hard` changes behavior, so as not to break scripts like the one under discussion. There may emerge new reset modes, but the existing ones won't changes. BTW, `git merge --abort` is just `git reset --merge` in disguise. – j6t Dec 15 '16 at 22:23
  • @j6t: agreed ... but there was Git 2.0. :-) – torek Dec 15 '16 at 22:25