1

I want to test to see if one branch can be merged into another. For example, say I want to test if a release branch can be merged into master, without actually merging into master. I figured I'd do something like this:

#!/usr/env/bin bash
git checkout master
git checkout -b master_temp
git merge my_release_branch

So I figure the merge has succeeded if the exit code is 0, and otherwise the merge failed.

Here is my big concern though: say the merge succeeds, but it opens up the interactive portion. How can I avoid that interactive bit? Sometimes during merges, nano or vim opens and we have to do something (not sure what). Is there a way to turn that off?

This question is basically the same, however, the question does not stipulate that this needs to be done by anything other than a human. In my case, it needs to be automatic/programmatic.

alex
  • 5,636
  • 9
  • 47
  • 97
Alexander Mills
  • 78,517
  • 109
  • 412
  • 724
  • I've found reference to `git merge-tree` [here](https://stackoverflow.com/a/6283843/27302), but I'm not sure how to use it in this case. Are you OK with modifying the working tree or the index, or do you want it to be completely side-effect free, or what? – Daniel H Jul 14 '18 at 19:22
  • @DanielH you know on Github where they tell if two branches can be merged (w/o actually merging them)? That's what I want to do. I'd rather have no side effects, I figure that's possible if I just checkout throwaway branches? – Alexander Mills Jul 14 '18 at 19:28
  • On GitHub they do actually perform the merge in a side branch; you can fetch `refs/pull/$prnumber/merge` (although I think this behavior is no longer part of the API and they might change it). Checking out another branch would work, but would mess up `HEAD` and, if you don't have a bare repository, the working tree. You can use [`git worktree`](https://git-scm.com/docs/git-worktree) to get around that. – Daniel H Jul 14 '18 at 19:32

2 Answers2

2

Running git merge will start your preferred editor1 if and only if all of the following conditions hold:

  • The merge starts successfully (i.e., the index is not in a bad state, and the arguments to git merge were all parsed successfully).
  • Git found or made a merge base. Older versions of Git will use the empty tree as a merge base for unrelated histories; newer ones require --allow-unrelated-histories.
  • The merge base thus found is not the current (HEAD) commit, or you used --no-ff.
  • The other commit you passed to git merge is not already an ancestor of the current commit. (For octopus merges, the rules are a little more complicated, but the difference should be clear enough: there is more than one "other commit".)
  • The merge succeeded without conflicts, or all conflicts were low-level conflicts resolved via an eXtended-strategy-option (-X ours or -X theirs). (Note that the -s ours strategy never has conflicts, making this constraint vacuous there.)
  • You did not pass a -m and merge message argument (or you did but added --edit as well; see commentary below this answer).
  • You did not specify --no-commit (the editor is invoked due to the merge commit being made!).

You can therefore guarantee that Git won't run your preferred editor by passing a merge message via -m. Alternatively, you can deliberately not pass a merge message but provide an environment GIT_EDITOR setting that invokes something other than an actual editor. For instance:

GIT_EDITOR=true git merge --quiet $hash

will run the merge to completion without opening an editor, or will fail because the merge itself stopped with conflicts, or never started in the first place. And, as Daniel H noted in comments below, --no-commit suppresses the final commit, hence suppresses the editor.

Besides these techniques, it's possible to invoke git merge-recursive directly. The git stash script does so. Be careful with this trick since it bypasses a lot of the usual safety checks.


1Your preferred editor is defined by the first of these various settings:

  • $GIT_EDITOR in the environment
  • core.editor as configured through git config
  • the compiled-in default editor

Using git var GIT_EDITOR will tell you which editor you have chosen, or defaulted-to.

torek
  • 389,216
  • 48
  • 524
  • 664
  • Doesn't that *actually do the merge* if possible? – Daniel H Jul 14 '18 at 18:45
  • @DanielH: Yes. You can opt to do it on a detached HEAD, or on a new branch; or you can reset it away. You must also be careful about fast-forwards since if `git merge` opted to do the merge as a fast-forward operation, `HEAD` needs to go back to `HEAD@{1}` or `ORIG_HEAD`, not just `HEAD^1`. – torek Jul 14 '18 at 18:46
  • I don't know how `--no-commit` interacts with the return code but that might match the desired behavior better, and it looks like `--no-edit` exists instead of using `GIT_EDITOR=true` but is discouraged. – Daniel H Jul 14 '18 at 19:15
  • @DanielH: `--no-commit` would work here too, yes. The `--no-edit` option is the default if you supply a message with `-m`; it's there sort of as a side effect of the boolean option parser, because the Git people wanted `--edit` to force invoking the editor when using `-m`, and when you say "this is a boolean flag" the built in parser adds the `--no-...` variety as well as the `--...` variety. – torek Jul 14 '18 at 19:18
  • So with the OP in mind using `--no-commit` and/or `-m` should prevent the default editor from opening? – Alexander Mills Jul 14 '18 at 19:29
  • @AlexanderMills: yes. You might want to provide a temporary index and even a temporary work-tree as well, depending on how much you want to leave the original Git repository alone. – torek Jul 14 '18 at 19:53
  • i am not sure i understand what the temp worktree or index is for. I am going to test the merge on temp branches, is that not safe enough? – Alexander Mills Jul 14 '18 at 20:28
  • Well: each repository comes with one index, which indexes / stages the contents of one work-tree. If someone is actively working in a repository, they are using both its index and its work-tree. The `git merge` command *also* uses the index and work-tree to do its job, so you must overwrite their work, or be unable to run if they have such work in progress, if you use the default index and work-tree that come with the repository. If they have no work in progress, this is not a problem. So: do they have work in progress? – torek Jul 14 '18 at 21:35
1

Late to the party, but you can do this with

git merge-tree $(git merge-base feature_branch master) feature_branch master
lbergnehr
  • 1,498
  • 10
  • 14