How to test a merge without actually merging first
Asked Answered
C

9

228

Is there any way of simulating a git merge between two branches, the current working branch and the master, but without making any changes?

I often have conflicts when I have to make a git merge. Is there any way of simulating the merge first?

Calaverite answered 20/9, 2011 at 11:12 Comment(1)
see also #501907Danika
A
178

I don't think there is a way of simulating what will happen until you try the merge. However, if you make sure that the output of git status is empty before you do the merge, it is quite safe to just go ahead and try it. If you get conflicts, you can immediately get back to the state you were at before with:

git reset --merge

Since git 1.7.4, you can also abort the merge by doing:

git merge --abort

(As the commit message that added that option explains, this was added for consistency with git rebase --abort and so on.)

Alessandraalessandria answered 20/9, 2011 at 11:16 Comment(7)
@Amber's answer is answering exactly what is being asked 'how to simulate the merge'. using --no-commit is much easier in my opinionPoolroom
@samirahmed: @Shout answered the question more literally, sure, although with --no-commit you're still changing the index and the working tree, which isn't exactly "without making any changes" :) My point is that when people ask this kind of question, it's generally because they're not aware that the best way to see how a merge would go is to just try the merge, often because they're not aware of how easy it is to get back to the state they were in before if there turned out to be problems.Alessandraalessandria
I don't know if this was added in a more recent version of git, but in the docs (1.8.4) it states "git merge --abort is equivalent to git reset --merge when MERGE_HEAD is present", so whatever's easier to remember :)Fraternal
@SamuelMeacham: thanks for pointing that out - it was introduced in 1.7.4. I've updated the answer with that. Thanks!Alessandraalessandria
This suggestion did not do anything for me, on git 1.9.4.Dewyeyed
@djangofan: Could you give more details about the situation? (Just guessing: if the merge succeeded without any conflicts, this command wouldn't do anything - one would need to reset to the commit before the merge.)Alessandraalessandria
@MarkLongair - sorry, I moved on from the merge issue I had when I discovered this question. I will try Ian's suggestion below, next time it happens, and I will try your steps again. Basically, the git abort you mentioned above just did absolutely nothing and had no error either.Dewyeyed
S
194

You can use git merge --no-commit to prevent the merge from actually being committed, and if you don't like how the merge works out, just reset to the original head.

If you definitely don't want to finalize the merge, even if it's a fast-forward (and thus has no conflicts, by definition), you could add --no-ff as well.

Shout answered 20/9, 2011 at 11:14 Comment(9)
I don't think that git merge --abort exists - perhaps you mean git reset --merge?Alessandraalessandria
Nah, I just forgot that unlike rebase there isn't a --abort for git merge.Shout
I'd throw on --no-ff too. To keep a ff merge from occurring.Gan
@Gan possibly - though since the OP seems to mostly be wanting to know if there are merge conflicts (which an FF merge by definition isn't going to have), it might not be necessary.Shout
@Andy's --no-ff is pretty much mandatory here, as --no-commit doesn't stop fast-forward changes.Labyrinth
I keep a alias handy. create one by using the command git config --global alias.tm "commit --no-commit --no-ff"(here tm i mean the short for od temporary merge.) and then git tm branch name (this you do while you have the target branch checked out)Sarsenet
@Anant Anand Gupta - this is a good trick but it should be: git config --global alias.tm "merge --no-commit --no-ff"Asternal
I believe that git merge --no-commit --no-ff may still delete a file foo that was removed via git rm foo.Protraction
Down voted because this results in uncommitted work. By merging master into your feature branch, this would create a commit which is always reversible.Treharne
A
178

I don't think there is a way of simulating what will happen until you try the merge. However, if you make sure that the output of git status is empty before you do the merge, it is quite safe to just go ahead and try it. If you get conflicts, you can immediately get back to the state you were at before with:

git reset --merge

Since git 1.7.4, you can also abort the merge by doing:

git merge --abort

(As the commit message that added that option explains, this was added for consistency with git rebase --abort and so on.)

Alessandraalessandria answered 20/9, 2011 at 11:16 Comment(7)
@Amber's answer is answering exactly what is being asked 'how to simulate the merge'. using --no-commit is much easier in my opinionPoolroom
@samirahmed: @Shout answered the question more literally, sure, although with --no-commit you're still changing the index and the working tree, which isn't exactly "without making any changes" :) My point is that when people ask this kind of question, it's generally because they're not aware that the best way to see how a merge would go is to just try the merge, often because they're not aware of how easy it is to get back to the state they were in before if there turned out to be problems.Alessandraalessandria
I don't know if this was added in a more recent version of git, but in the docs (1.8.4) it states "git merge --abort is equivalent to git reset --merge when MERGE_HEAD is present", so whatever's easier to remember :)Fraternal
@SamuelMeacham: thanks for pointing that out - it was introduced in 1.7.4. I've updated the answer with that. Thanks!Alessandraalessandria
This suggestion did not do anything for me, on git 1.9.4.Dewyeyed
@djangofan: Could you give more details about the situation? (Just guessing: if the merge succeeded without any conflicts, this command wouldn't do anything - one would need to reset to the commit before the merge.)Alessandraalessandria
@MarkLongair - sorry, I moved on from the merge issue I had when I discovered this question. I will try Ian's suggestion below, next time it happens, and I will try your steps again. Basically, the git abort you mentioned above just did absolutely nothing and had no error either.Dewyeyed
S
140

If I want to compare changes on a topic branch to master, I find it easiest and safest to do the following:

git checkout master
git checkout -b trial_merge
git merge topic_branch

After completing the merge, it is easy to see the consolidated change from master

git diff master

When done, simply delete the trial_merge branch

git checkout master
git branch -D trial_merge

This way, the master branch never changes.

Spittle answered 17/2, 2014 at 11:36 Comment(3)
You can also do git checkout --detach and test anything you want. Later, if you want to keep your changes, do git checkout -b new_branch. And if you want to throw your changes away, checkout any branch you want (git checkout master).Latonya
If topic_branch is huge (as is probably the case if you're at this question in the first place) the diff masteroutput is probably too large for you to eyeball if a merge is going to cause conflicts.Jerrilyn
I definitely like this a lot ... safe and simple.Dewan
T
15

Here is the solution that I have found: git merge-tree does merging "in memory" and prints the diff without touching your working directory. You can even test a branch without checking it out.

Get the merge diff

First, do this to make sure your repository knows about all the remote branches:

$ git fetch --all

Now use this bash snippet to see how branch $branch would merge into $master:

$ branch='feature'
$ git merge-tree $(git merge-base $branch master) master $branch

No changes are made to your workdir or index. It's a dry-run merge.

Pick information from the output

The output is a diff. In case the branch has been merged, it will be empty.

To find whether there are conflicts, grep it for <<<:

$ git merge-tree $(git merge-base $branch master) master $branch | fgrep '<<<'

To extract conflict diffs, use sed to extract lines between <<< and >>>:

$ git merge-tree $(git merge-base $branch master) master $branch | \
  sed -ne '/^\+<<</,/^\+>>>/ p'

Features

  • The diff will be empty if a branch is already merged
  • Use grep/sed to extract conflicts information
  • Use origin/feature to test branches you've never worked with
  • Can be used to see how 2 branches have diverged

Add it to your favorites

Get the diff of the merge:

git config --global alias.mergediff '!f(){ branch="$1" ; into="$2" ; git merge-tree $(git merge-base "$branch" "$into") "$into" "$branch" ; };f '

Usage:

$ git mergediff <feature-branch> <merge-into>
$ git mergediff feature master

Get merge conflicts:

git config --global alias.mergetest '!f(){ git mergediff $@ | sed -ne "/^+<<</,/^+>>>/ p" ; };f '

Usage:

$ git mergetest <feature-branch> <merge-into>
$ git mergetest feature master
Travail answered 7/9, 2020 at 11:47 Comment(1)
Bravo! Your "git merge-tree" statement checks whether a merge would result in conflicts without disturbing the work area of the local repository. This is perfect in an environment where Git would an updater.Ivo
A
7

Why not just create a throwaway branch (git checkout -b), and do a test merge there?

Arpent answered 16/6, 2017 at 6:26 Comment(1)
What you suggest is actually the answer by Ian expressed tersely :)Matter
A
5

I use :

git merge --ff-only

according to documentation:

Refuse to merge and exit with a non-zero status unless the current HEAD is already up-to-date or the merge can be resolved as a fast-forward.

It's not really a simulation because there will be a fast-forward merge in case of no conflicts between the two branches. But in case of conflicts, you will be informed and nothing will happens.

Adulterine answered 30/8, 2016 at 13:16 Comment(1)
This will fail even if there isn't conflicts between the 2 branches, unless (as it says) both branches points to the same commit, or a fast-forward merge is possible.Anetteaneurin
M
3

I've been able to use git merge --abort, recently. However, this can only be used if there is a merge conflict. If you are sure that you will not want to commit, then use the other mentioned methods above.

Mandi answered 9/9, 2013 at 14:50 Comment(1)
Which other methods mentioned above? They all mention git merge --abort. You should future proof your answer by specifying who wrote the answer you're referring to.Darrondarrow
M
0

I would like to add to the excellent answer from @kolypto - (this should be a comment but I don't have the points).

The man page for git merge-tree states, under "Mistakes to avoid":

Do NOT look through the resulting toplevel tree to try to find which files conflict [...] there are numerous types of conflicts not representable by conflict markers (modify/delete, mode conflict, binary file changed on both sides, file/directory conflicts, various rename conflict permutations, etc.)

...so doing an fgrep '<<<' on the output of git merge-tree is not the correct way to determine if there are conflicts. Instead you should check the exit code of git merge-tree:

For a successful, non-conflicted merge, the exit status is 0. When the merge has conflicts, the exit status is 1. If the merge is not able to complete (or start) due to some kind of error, the exit status is something other than 0 or 1 (and the output is unspecified).

Example:

#!/bin/bash

branch='myFeatureBranch'
ret=0
mergeTest=`git merge-tree --write-tree master $branch` || ret=$?
if [ ! $ret -eq 0 ];then
   echo "Merge would result in conflicts:"
   echo "$mergeTest" | grep CONFLICT
   ## Do something useful here
   exit 1
fi
Michelinemichell answered 23/11, 2023 at 14:29 Comment(0)
P
-2

I don't know exactly if it is your case, but your question remember me that sometimes I start a feature, I commit over the days and I merge the develop on it many times.

On this point I lose the control over the exact files I changed and I will only know it when my feature were closed and my code go to develop.

In this case, a good way to know what modifications you did (not other from the merges) is using Sourcetree.

You must click with the right button on the base branch and select Diff Against Current:

Sourcetree's feature to know the diff between two branches

Then sourcetree will show you all the modifications that will be merged if you merge your branch into base branch.

Results

Of course, it will not show you the conflicts, but it is a useful tool in merges.

Pastorship answered 14/6, 2018 at 17:2 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.