最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

git - How to find all branches with merge conflicts? - Stack Overflow

programmeradmin0浏览0评论

I know various ways to list git branches (just git branches or get for-each-ref) as well as how to check each individual branch if it has conflicts with another (lets assume origin/develop for now):

git merge --no-commit --no-ff | awk '$1 == "CONFLICT" {print $NF}' && git merge --abort

But in lieu of doing a dry run merge on every branch (yeughh), is there a way to list all the conflicted branches/Branches with conflicted files etc?

I know various ways to list git branches (just git branches or get for-each-ref) as well as how to check each individual branch if it has conflicts with another (lets assume origin/develop for now):

git merge --no-commit --no-ff | awk '$1 == "CONFLICT" {print $NF}' && git merge --abort

But in lieu of doing a dry run merge on every branch (yeughh), is there a way to list all the conflicted branches/Branches with conflicted files etc?

Share Improve this question edited Feb 6 at 18:16 Guildenstern 3,8012 gold badges28 silver badges52 bronze badges asked Feb 6 at 16:12 AncientSwordRageAncientSwordRage 7,61521 gold badges99 silver badges190 bronze badges 2
  • Did you want the list of conflicted branches relative to a given branch (origin/develop, in your example), or did you want to check every possible combination of branches? – ipodtouch0218 Commented Feb 6 at 16:14
  • 1 No, there's no global way to know, looping through refs is indeed the way to go, albeit impractical. (That being said, it's git merge --abort, but I guess it's only a typo here, we get the point.) – Romain Valeri Commented Feb 6 at 16:15
Add a comment  | 

4 Answers 4

Reset to default 3

git-merge-tree(1) does an in-memory merge and outputs the hash of the merge, if successful. You can use that with git-for-each-ref(1) to, say, loop over branches which are not merged to whatever other ref yet.

#!/usr/bin/env bash

upstream=origin/main

for b in $(git for-each-ref \
        --format="%(refname:short)" \
        'refs/heads' --no-merged=$upstream)
do
    git merge-tree $upstream $b >/dev/null 2>&1 \
         || printf "%s has conflicts with %s\n" "$b" "$upstream"
done

See also the “Usage Notes” section in the manual: [1]

vi message.txt
BRANCH1=refs/heads/test
BRANCH2=main
NEWTREE=$(git merge-tree --write-tree $BRANCH1 $BRANCH2) || {
    echo "There were conflicts..." 1>&2
    exit 1
}
NEWCOMMIT=$(git commit-tree $NEWTREE -F message.txt \
    -p $BRANCH1 -p $BRANCH2)
git update-ref $BRANCH1 $NEWCOMMIT

The example script from the manual also just checks for non-zero exit status. So that is apparently enough to check for conflicts. Although at least one other failure mode is if the two histories are unrelated (see --allow-unrelated-histories).

Notes

  1. git version 2.48.1

But in lieu of doing a dry run merge on every branch, is there a way to list all the conflicted branches / branches with conflicted files etc?

No. The reason is that Git does not know this. It doesn't know there is a conflict (of any kind) until it attempts to enact the merge — and in order to enact a merge, the branch to be merged into must be checked out, because Git also needs a place to enact the merge.

The definition of "conflict" depends almost entirely on your merge options. Are you ignoring whitespace changes? Renormalizing for updated cross-platform eol conventions? Adopting incoming changes as improvements on existing ones?

Both tips having changes to existing files isn't necessarily, and in many workflows is often not, a conflict. You can tell Git what exactly you're considering a conflict for this merge; it has and will use factory defaults if you don't tell it differnt but the only way to tell what any particular automerge settings will regard as a conflict is to run with them.

At that point, you might as well just do a --no-commit merge. You do not need to do a full checkout for this. git clone -ns . `mktemp -d`; cd $_; git reset -q origin/$onebranch; git merge $optionshere origin/$theother will run a minimum-checkout merge with your desired options; if you're using lfs or other custom configs you'll probably want a --template option on the clone; whichever, if the works you had no conflicts, if it doesn't you'll have them all (and just the ones that needed looking at) in your new temporary work tree.

Either way, the entire operation is so cheap it can be just abandoned, ordinary tempfile cleanup will get around to deleting the detritus. For instance, doing this with 20 years of linux history cost about two seconds and 8MB total. Nothing.

You could take a look at what git merge-tree can do for you

https://git-scm.com/docs/git-merge-tree

发布评论

评论列表(0)

  1. 暂无评论