How to determine if Git merge is in process

20.4k views Asked by At

Is there a Git command that can be used to determine if a merge is in-process (i.e. uncommitted)? I know I can simply check for .git/MERGE_HEAD, but is this proper and/or future-proof for command-line scripts?

5

There are 5 answers

4
pathfinderelite On BEST ANSWER

One trick is to use a Git command that will fail if a merge is in progress. You can then check the return code of the command. You'll also want to make sure that the command will not affect your working copy or index in the event that it succeeds. While there are many commands that fall into this category, one that seems appropriate is

git merge HEAD

which returns a 128 code if a merge is in progress, but 0 otherwise. Note that when a merge is not in-process, this command will simply print Already up-to-date since you are just merging with yourself. So, for scripting purposes, you can do this (in BASH)

git merge HEAD &> /dev/null
result=$?
if [ $result -ne 0 ]
then
    echo "Merge in progress."
else
    echo "Merge not in progress."
fi

Note that even with the --quiet flag of git merge, an in-process merge will still cause this command to print to the error stream. This is why I redirect its output to /dev/null.

1
tonoman3g On

git status

you can run git status

git will tell you what happening in your repository.

E.g. * conflicting files (unmerged files)

2
Edward Thomson On

You can safely check for the existence of MERGE_HEAD in your git directory[1] to determine whether there's a merge in progress. The MERGE_HEAD file contains the commit ids that are being merged in, that will be the nth parents of the committed merge. For example, if I try to merge branch br1 which is at c085e0c:

> git merge --no-ff --no-commit br1
Automatic merge went well; stopping before committing as requested

> cat .git/MERGE_HEAD
c085e0caa2598064bfde9cc6318bd2c73fee2371

If you are doing an octopus merge, then you will see more than one commit id in this file (newline separated):

> git merge --no-ff --no-commit br2 br3
Fast-forwarding to: br2
Trying simple merge with br3
Automatic merge went well; stopping before committing as requested

> cat .git/MERGE_HEAD
69b0169b1cba60de86161b375f013c59ad9581d8
99dad0187351d61ae8e88d49c96d7383f9e8fa6d

Using MERGE_HEAD is actually how git clients determine whether there's a merge in progress. Some provide this insight through leaky abstractions:

> git merge --abort
fatal: There is no merge to abort (MERGE_HEAD missing).

So checking for the presence of MERGE_HEAD is perfectly acceptable and is is as future proof as anything in software - meaning that any changes to git-merge would have to take compatibility with other git clients into account and would (hopefully!) gracefully transition and/or provide backward compatibility.

[1] You can trust the existence of MERGE_HEAD much more than you can trust that .git is underneath your working directory. Somebody could use the --git-dir flag or the GIT_DIR environment variable.

0
VonC On

Another option would be to test for the presence of a .git/MERGE_MSG file.

That is because, before 2.14.x/2.15 (Q3 2017), you can end up in a situation where you do not have .git/MERGE_HEAD, even though the merge is in progress.

See commit 9d89b35, commit 8e6a6bb, commit 62dc42b (23 Aug 2017), and commit e2de82f (21 Aug 2017) by Michael J Gruber (mjg).
(Merged by Junio C Hamano -- gitster -- in commit 6e6ba65, 27 Aug 2017)

Killing "git merge --edit" before the editor returns control left the repository in a state with MERGE_MSG but without MERGE_HEAD, which incorrectly tells the subsequent "git commit" that there was a squash merge in progress.
This has been fixed.

After Git 2.14.x/2.15, that won't be the case anymore, and testing for .git/MERGE_HEAD will be enough.

1
akhan On

Since MERGE_HEAD is only available during a merge and is also future-proof, we can simply use git rev-list -1 MERGE_HEAD (conveniently, a plumbing command) which will exit with code 128 if MERGE_HEAD is not found. Pipe stdout and stderr to /dev/null for a cleaner check. Or even better, use git rev-parse -q --verify MERGE_HEAD.