[git] How can I preview a merge in git?

I have a git branch (the mainline, for example) and I want to merge in another development branch. Or do I?

In order to decide whether I really want to merge this branch in, i'd like to see some sort of preview of what the merge will do. Preferably with the ability to see the list of commits that are being applied.

So far, the best I can come up with is merge --no-ff --no-commit, and then diff HEAD.

This question is related to git git-merge

The answer is


I do not want to use the git merge command as the precursor to reviewing conflicting files. I don't want to do a merge, I want to identify potential problems before I merge - problems that auto-merge might hide from me. The solution I have been searching for is how to have git spit out a list of files that have been changed in both branches that will be merged together in the future, relative to some common ancestor. Once I have that list, I can use other file comparison tools to scout things out further. I have searched multiple times, and I still haven't found what I want in a native git command.

Here is my workaround, in case it helps anyone else out there:

In this scenario I have a branch called QA that has many changes in it since the last production release. Our last production release is tagged with "15.20.1". I have another development branch called new_stuff that I want to merge into the QA branch. Both QA and new_stuff point to commits that "follow" (as reported by gitk) the 15.20.1 tag.

git checkout QA
git pull
git diff 15.20.1 --name-only > QA_files
git checkout new_stuff
git pull
git diff 15.20.1 --name-only > new_stuff_files
comm -12 QA_files new_stuff_files

Here are some discussions that hit on why I'm interested in targeting these specific files:

How can I trust Git merge?

https://softwareengineering.stackexchange.com/questions/199780/how-far-do-you-trust-automerge


Maybe this can help you ? git-diff-tree - Compares the content and mode of blobs found via two tree objects


  • git log ..otherbranch
    • list of changes that will be merged into current branch.
  • git diff ...otherbranch
    • diff from common ancestor (merge base) to the head of what will be merged. Note the three dots, which have a special meaning compared to two dots (see below).
  • gitk ...otherbranch
    • graphical representation of the branches since they were merged last time.

Empty string implies HEAD, so that's why just ..otherbranch instead of HEAD..otherbranch.

The two vs. three dots have slightly different meaning for diff than for the commands that list revisions (log, gitk etc.). For log and others two dots (a..b) means everything that is in b but not a and three dots (a...b) means everything that is in only one of a or b. But diff works with two revisions and there the simpler case represented by two dots (a..b) is simple difference from a to b and three dots (a...b) mean difference between common ancestor and b (git diff $(git merge-base a b)..b).


Pull Request - I've used most of the already submitted ideas but one that I also often use is ( especially if its from another dev ) doing a Pull Request which gives a handy way to review all of the changes in a merge before it takes place. I know that is GitHub not git but it sure is handy.


If you're like me, you're looking for equivalent to svn update -n. The following appears to do the trick. Note that make sure to do a git fetch first so that your local repo has the appropriate updates to compare against.

$ git fetch origin
$ git diff --name-status origin/master
D       TableAudit/Step0_DeleteOldFiles.sh
D       TableAudit/Step1_PopulateRawTableList.sh
A       manbuild/staff_companies.sql
M       update-all-slave-dbs.sh

or if you want a diff from your head to the remote:

$ git fetch origin
$ git diff origin/master

IMO this solution is much easier and less error prone (and therefore much less risky) than the top solution which proposes "merge then abort".


git log currentbranch..otherbranch will give you the list of commits that will go into the current branch if you do a merge. The usual arguments to log which give details on the commits will give you more information.

git diff currentbranch otherbranch will give you the diff between the two commits that will become one. This will be a diff that gives you everything that will get merged.

Would these help?


Short of actually performing the merge in a throw away fashion (see Kasapo's answer), there doesn't seem to be a reliable way of seeing this.

Having said that, here's a method that comes marginally close:

git log TARGET_BRANCH...SOURCE_BRANCH --cherry

This gives a fair indication of which commits will make it into the merge. To see diffs, add -p. To see file names, add any of --raw, --stat, --name-only, --name-status.

The problem with the git diff TARGET_BRANCH...SOURCE_BRANCH approach (see Jan Hudec's answer) is, you'll see diffs for changes already in your target branch if your source branch contains cross merges.


Adding to the existing answers, an alias could be created to show the diff and/or log prior to a merge. Many answers omit the fetch to be done first before "previewing" the merge; this is an alias that combines these two steps into one (emulating something similar to mercurial's hg incoming / outgoing)

So, building on "git log ..otherbranch", you can add the following to ~/.gitconfig :

...
[alias]
    # fetch and show what would be merged (use option "-p" to see patch)
    incoming = "!git remote update -p; git log ..@{u}"

For symmetry, the following alias can be used to show what is committed and would be pushed, prior to pushing:

    # what would be pushed (currently committed)
    outgoing = log @{u}..

And then you can run "git incoming" to show a lot of changes, or "git incoming -p" to show the patch (i.e., the "diff"), "git incoming --pretty=oneline", for a terse summary, etc. You may then (optionally) run "git pull" to actually merge. (Though, since you've already fetched, the merge could be done directly.)

Likewise, "git outgoing" shows what would be pushed if you were to run "git push".


Most answers here either require a clean working directory and multiple interactive steps (bad for scripting), or don't work for all cases, e.g. past merges which already bring some of the outstanding changes into your target branch, or cherry-picks doing the same.

To truly see what would change in the master branch if you merged develop into it, right now:

git merge-tree $(git merge-base master develop) master develop

As it's a plumbing command, it does not guess what you mean, you have to be explicit. It also doesn't colorize the output or use your pager, so the full command would be:

git merge-tree $(git merge-base master develop) master develop | colordiff | less -R

https://git.seveas.net/previewing-a-merge-result.html

(thanks to David Normington for the link)

P.S.:

If you would get merge conflicts, they will show up with the usual conflict markers in the output, e.g.:

$ git merge-tree $(git merge-base a b ) a b 
added in both
  our    100644 78981922613b2afb6025042ff6bd878ac1994e85 a
  their  100644 61780798228d17af2d34fce4cfbdf35556832472 a
@@ -1 +1,5 @@
+<<<<<<< .our
 a
+=======
+b
+>>>>>>> .their

User @dreftymac makes a good point: this makes it unsuitable for scripting, because you can't easily catch that from the status code. The conflict markers can be quite different depending on circumstance (deleted vs modified, etc), which makes it hard to grep, too. Beware.


If you already fetched the changes, my favourite is:

git log ...@{u}

That needs git 1.7.x I believe though. The @{u} notation is a "shorthand" for the upstream branch so it's a little more versatile than git log ...origin/master.

Note: If you use zsh and the extended glog thing on, you likely have to do something like:

git log ...@\{u\}