1

Is there a simple git command that can tell (e.g. by exit status) whether a work tree has unmerged paths / a merge conflict? Like when a git merge operation fails and git returns to the shell and git status shows that there are merge conflicts.

I found so far git status and a list of values it would output in an unmerged situation (the XY status codes then):

X          Y     Meaning
-------------------------------------------------
D           D    unmerged, both deleted
A           U    unmerged, added by us
U           D    unmerged, deleted by them
U           A    unmerged, added by them
D           U    unmerged, deleted by us
A           A    unmerged, both added
U           U    unmerged, both modified
-------------------------------------------------

So that the only way to detect so for me so far would be to match against a list of XY codes that represent unmerged, e.g.:

AA | DD | [ADU]U | U[AD]

(added horizontal white space for readability)

A check with zero exit status in case of unmerged paths (or non-zero if none) then would be (if my understanding of git status is correct here):

git status --porcelain -z \
  | grep -q -z '^\(AA\|DD\|[ADU]U\|U[AD]\) '

This becomes rather convoluted and I'm looking for a more simple command (best with git only).

I want to use it in bash script for a local build that rejects further processing if there are any unmerged paths in the git repositories work tree.

hakre
  • 193,403
  • 52
  • 435
  • 836
  • Unless you're using `git checkout -m`, a *checkout* operation never merges anything and therefore never produces a merge conflict. (You have `checkout` specifically in your question title/subject.) The only way you could have a merge conflict for such an operation is if there was one *before* the `git checkout`. Is that what you're trying to detect? – torek May 10 '19 at 13:02
  • It's also worth mentioning that "unmerged" is *always* an *index* state. `git status` has to produce more than just index state, though, and except when using `--porcelain=v2`, it combines the in-index state information with the index-vs-work-tree state information, which is not an information-preserving operation. If you just want to find out if the index is in an unmerged state, use `git write-tree`, which succeeds if all entries are at stage 0 and fails if any are nonzero (with a side effect of creating a tree object). – torek May 10 '19 at 13:23
  • @torek: The repository could have had a failing merge or cherry pick and be left in that state. Just want to exit the local build script early in such a case. And also my wording about index state and work tree might not be very precise. I changed from checkt to just non-bare repository so that it is clear the repository has a work-tree on which the check would take place. I also added the command I have so far and it's exit status. – hakre May 10 '19 at 17:00
  • 1
    OK, yes, if your goal is to check for a previous command that left some unmerged state, the easiest way to check is to use `git write-tree`. If you don't want to write a tree object, you can use `git ls-files --stage` to check for any nonzero stage entries. – torek May 10 '19 at 17:45
  • `git ls-files -u | grep -q .` (or `--unmerged`) might be better, but I'd go with the `git write-tree` for simplicity, odds seem pretty high you're going to be writing the tree anyway if that succeeds. – jthill May 10 '19 at 17:56
  • Thanks for all these comments. I now came to the following `test ! -z "$(git ls-files --unmerged --exclude-standard | head --bytes=1)"` - I can't say for which criteria is is better or worse than the git-status variant, what I do see is that the listing is much more reduced for the check. – hakre May 10 '19 at 18:49

1 Answers1

1

There's already answer to that question here: https://stackoverflow.com/a/501461/1150795.

Provide --no-commit flag during the merge as follows:

git merge --no-commit --no-ff $BRANCH

Then examine staged changes:

git diff --cached

To undo merge, type:

git merge --abort

Alternatively you can compare your local branch against the remote branch if that's your case:

git fetch origin/master
git diff master origin/master
Piotr Wittchen
  • 3,853
  • 4
  • 26
  • 39
  • Good solution. Maybe consider adding a `--diff-filter=U` flag to your diff at the end to only output unmerged pathes. – Romain Valeri May 10 '19 at 12:25
  • Thanks for your answer and the comment. The other Q&A material is nor really relevant for reasons: The build script does not merge (and to detect a failing merge has been answered in different Q&As already). And it should operate on index and work tree. So thanks again for answering, but my question is not about merge nor to expect remote repositories, it's just a local build script operating on a development work tree which should reject to build if there is anything unmerged / in conflict in the (local, non-bare) git repository. And there is no filter for `git status` unluckily. – hakre May 10 '19 at 12:42