Какой самый простой способ перечислить конфликтующие файлы в Git?

Мне просто нужен простой список конфликтующих файлов.

Что может быть проще, чем:

git ls-files -u  | cut -f 2 | sort -u

or:

git ls-files -u  | awk '{print $4}' | sort | uniq

Думаю, я мог бы настроить для этого удобный alias, однако мне было интересно, как это делают профессионалы. Я бы использовал его для написания циклов оболочки, например. для автоматического разрешения конфликтов и т. д. Может быть, заменить этот цикл подключением к mergetool.cmd?


person inger    schedule 17.06.2010    source источник
comment
git rebase --continue отобразит файлы с конфликтами (если есть)   -  person Jakob Jingleheimer    schedule 08.08.2014
comment
git status достаточно   -  person Amruth A    schedule 08.08.2018
comment
В конфликтной сессии слияния git merge --continue покажет список файлов с конфликтами.   -  person Jayan    schedule 18.05.2019
comment
git rebase --continue не перечислял конфликты, просто сказал мне исправить их (git версия 2.21.0)   -  person Gary    schedule 04.09.2019


Ответы (20)


git diff --check

отобразит список файлов, содержащих маркеры конфликтов, включая номера строк.

Например:

> git diff --check
index-localhost.html:85: leftover conflict marker
index-localhost.html:87: leftover conflict marker
index-localhost.html:89: leftover conflict marker
index.html:85: leftover conflict marker
index.html:87: leftover conflict marker
index.html:89: leftover conflict marker

источник: https://ardalis.com/detect-git-conflict-markers

person cnlevy    schedule 20.03.2018
comment
Я обнаружил, что git diff --check сообщает мне и о других (менее серьезных) проблемах, таких как завершающие пробелы, поэтому git diff --check | grep -i conflict может быть подходящим для случая OP - person CCJ; 06.12.2019
comment
git diff --check использует правила пробелов из core.whitespace. Вы можете отключить все проверки пробелов во время git вызова, чтобы просто получить маркеры конфликта: git -c core.whitespace=-trailing-space,-space-before-tab,-indent-with-non-tab,-tab-in-indent,-cr-at-eol diff --check - person Josh Cooley; 01.09.2020
comment
отлично! он также показывает такие вещи, как завершающий ws ‹3 - person CervEd; 26.03.2021
comment
git diff --check возвращает пустое значение, даже git diff --name-only --diff-filter=U возвращает файлы, это нормально? - person alper; 09.07.2021

Пытаюсь ответить на свой вопрос:

Нет, кажется, нет более простого способа, чем тот, который указан в вопросе, из коробки.

После того, как я набрал это слишком много раз, просто вставил более короткий в исполняемый файл с именем 'git-columns', доступный для git, теперь я могу просто: git conflicts получить список, который я хотел.

Обновление: как предлагает Ричард, вы можете настроить псевдоним git в качестве альтернативы исполняемому файлу

git config --global alias.conflicts '!git ls-files -u | cut -f 2 | sort -u'

Преимущество использования исполняемого файла перед псевдонимом заключается в том, что вы можете поделиться этим скриптом с членами команды (в части репозитория bin dir).

person inger    schedule 26.06.2010
comment
Я чувствовал то же самое в тот момент - думал, как, черт возьми, людям это не нужно, и видел, насколько тривиальным было обходное решение. Однако я использую git уже 2 года и, честно говоря, больше не сталкивался с этим ограничением. Так, может быть, это не так уж и часто? - person inger; 19.10.2011
comment
Это достаточно просто, чтобы вы могли установить для него псевдоним git config --global alias.conflicts "!git ls-files -u | cut -f 2 | sort -u" (! Означает запуск этой команды оболочки, а не просто команды git). - person Richard; 09.04.2012
comment
Стоит упомянуть, что вам на самом деле нужны одинарные кавычки вместо двойных кавычек. В противном случае ! будет интерпретироваться вашей оболочкой: git config --global alias.conflicts '!git ls-files -u | cut -f 2 | sort -u' - person umop; 02.06.2012

Вот надежный способ:

grep -H -r "<<<<<<< HEAD" /path/to/project/dir
person Jones Agyemang    schedule 16.12.2013
comment
Нет. Индекс Git по-прежнему будет внутренне отмечать определенные файлы как конфликтующие даже после удаления текстовых маркеров в файлах. - person Alexander Bird; 24.04.2014
comment
Наряду с комментарием Александра, по-прежнему полезно видеть это как вариант :) Пожалуйста, не удаляйте. - person WoodenKitty; 13.10.2014
comment
Или для запуска в текущем рабочем каталоге используйте точку для пути - grep -H -r "<<<<<<< HEAD" . - person David Douglas; 03.03.2016
comment
Хе-хе, я тоже так поступаю. Добавление c также приводит к подсчету конфликтов! Одно замечание: я бы использовал флаги -Hrn, которые также будут предоставлять информацию о номере строки. - person ShellFish; 18.04.2016
comment
Если вы используете регулярное выражение, я бы предложил вместо этого [<=>]{7}. (Для этого может понадобиться -E флаг для работы в grep.) Или <{7}, если вы не беспокоитесь о висящих маркерах слияния или хотите подсчитать конфликты. (Вы также можете использовать git grep - тогда вам не нужен флаг -r.) - person celticminstrel; 06.08.2016
comment
Флаг H означает, что будет показано имя файла. r означает рекурсивный. Если вы делаете git grep, вы ставите --files-with-matches вместо флага H. - person Timo; 24.09.2017
comment
Гораздо быстрее использовать команду git grep для больших баз кода, потому что она будет следовать правилам, настроенным в файле .gitignore. git grep -H -r "<<<<<< HEAD" - person wyattis; 26.03.2020
comment
Для git stash apply << HEAD там не будет. Вместо этого `‹( Обновлено Upstream - person Reed; 26.09.2020
comment
Если вы В своем каталоге git, используйте grep -Hrn "<<<<<<< " "$(git rev-parse --show-toplevel)", и он будет искать из корня вашего проекта. - person Reed; 26.09.2020

git status отображает "оба измененных" рядом с файлами, у которых есть конфликты, вместо "измененный" или "новый файл" и т. Д.

person Rafa    schedule 19.10.2011
comment
Это правда. Однако этот конкретный вопрос касался простого списка конфликтующих файлов ... это может быть проблема XY (я не могу вспомнить, зачем мне действительно был нужен этот список конфликтов, но тот факт, что он мне не нужен с тех пор, может означать, что я должен тогда следовали другому подходу. Не уверен сейчас .. Я также писал сценарии для автоматического разрешения конфликтов импорта java, которым нужен этот список, т.е. неинтерактивное использование) .. - person inger; 25.10.2011
comment
О, я этого не понял. Я думал, вам нужен нормальный список для нормального использования. Вот почему я испугался вашего собственного кода и вашего самоответа ... потом я понял, что обе модифицированные штуки работают на меня (и я предположил, что вы просто хотите того же, что и я, почему бы вам не? ;-P) Спасибо за голос :) - person Rafa; 26.10.2011
comment
Также могут возникать конфликты слияния, когда одна ветвь удаляет файл, а другая изменяет его. Они не будут отображаться с git status | grep "both modified". - person Kalinda Pride; 12.10.2020

Это работает для меня:

git grep '<<<<<<< HEAD'

or

git grep '<<<<<<< HEAD' | less -N

person user218867    schedule 27.10.2016
comment
Конфликты могут включать измененные и удаленные файлы, на которые это решение не распространяется. - person Koenigsberg; 11.04.2019

вы можете нажать git ls-files -u в командной строке, в нем перечислены файлы с конфликтами

person Emil Reña Enriquez    schedule 11.08.2015

Если вы попытаетесь выполнить фиксацию и возникнут конфликты, git предоставит вам список неразрешенных на данный момент конфликтов ... но не в виде простого списка. Обычно это то, что вам нужно при интерактивной работе, потому что список становится короче по мере устранения конфликтов.

person Tel    schedule 04.08.2011
comment
интерактивно, потому что список становится короче по мере устранения конфликтов. Интересно. Я всегда использовал для этого mergetool. - person inger; 25.10.2011

Возможно, это было добавлено в Git, но файлы, которые еще предстоит разрешить, перечислены в сообщении о состоянии (статус git) следующим образом:

#
# Unmerged paths:
#   (use "git add/rm <file>..." as appropriate to mark resolution)
#
#   both modified:      syssw/target/libs/makefile
#

Обратите внимание, что это раздел "Не объединенные пути".

person Patrick O'Hara    schedule 21.04.2015

Я бы также предложил следующую команду, если вы работаете в локальном репозитории git или в каталоге, в котором был применен patch -p1 --merge < ....

grep -rnw . -e '^<<<<<<<$'
person Deniz da King    schedule 21.02.2021

Предполагая, что вы знаете, где находится ваш корневой каталог git, $ {GIT_ROOT}, вы можете:

 cat ${GIT_ROOT}/.git/MERGE_MSG | sed '1,/Conflicts/d'
person Tzunghsing David Wong    schedule 10.08.2018

Я всегда просто использовал git status.

можно добавить awk в конце, чтобы получить только имена файлов

git status -s | grep ^U | awk '{print $2}'

person Ascherer    schedule 24.01.2014

Мои 2 цента здесь (даже когда много крутых / рабочих отзывов)

Я создал этот псевдоним в моем .gitconfig

[alias]
 ...
 conflicts = !git diff --name-only --diff-filter=U | grep -oE '[^/ ]+$'

который покажет мне только имена файлов с конфликтами ... а не весь их путь :)

person Manu    schedule 10.12.2018

Вот что я использую для списка измененных файлов, подходящих для подстановки в командной строке в bash

git diff --numstat -b -w | grep ^[1-9] | cut -f 3

Для редактирования списка используйте замену $(cmd).

vi $(git diff --numstat -b -w | grep ^[1-9] | cut -f 3)

Не работает, если в именах файлов есть пробелы. Я попытался использовать sed, чтобы экранировать или заключать пробелы в кавычки, и список вывода выглядел правильно, но подстановка $() по-прежнему не работала должным образом.

person Darrel Lee    schedule 06.03.2019

Утилита git wizard https://github.com/makelinux/git-wizard считает отдельно неразрешенные конфликты изменения (коллизии) и неслитые файлы. Конфликты необходимо разрешать вручную или с помощью mergetool. Решенные несмешанные изменения можно добавить и зафиксировать с помощью git rebase --continue.

person Costa    schedule 05.05.2020

ответ Джонса Агьеманга, вероятно, достаточен для большинства случаев использования и стал отличной отправной точкой для моего решения. Для написания сценариев в Git Bent, созданной мной библиотеке-оболочке git, мне нужно было кое-что побольше крепкий. Я публикую написанный мной прототип, который еще не полностью адаптирован к сценариям.

Примечания

  • Связанный ответ проверяет <<<<<<< HEAD, что не работает для конфликтов слияния из-за использования git stash apply, имеющего <<<<<<< Updated Upstream
  • Мое решение подтверждает наличие ======= & >>>>>>>
  • Связанный ответ, безусловно, более эффективен, так как он не должен делать столько
  • Мое решение НЕ предоставляет номера строк

Печать файлов с конфликтами слияния

Вам нужна функция str_split_line снизу.

# Root git directory
dir="$(git rev-parse --show-toplevel)"
# Put the grep output into an array (see below)
str_split_line "$(grep -r "^<<<<<<< " "${dir})" files
bn="$(basename "${dir}")"
for i in "${files[@]}"; do 
    # Remove the matched string, so we're left with the file name  
    file="$(sed -e "s/:<<<<<<< .*//" <<< "${i}")"

    # Remove the path, keep the project dir's name  
    fileShort="${file#"${dir}"}"
    fileShort="${bn}${fileShort}"

    # Confirm merge divider & closer are present
    c1=$(grep -c "^=======" "${file}")
    c2=$(grep -c "^>>>>>>> " "${file}")
    if [[ c1 -gt 0 && c2 -gt 0 ]]; then
        echo "${fileShort} has a merge conflict"
    fi
done

Вывод

projectdir/file-name
projectdir/subdir/file-name

Разделить строки по линейной функции

Вы можете просто скопировать блок кода, если не хотите, чтобы это была отдельная функция.

function str_split_line(){
# for IFS, see https://stackoverflow.com/questions/16831429/when-setting-ifs-to-split-on-newlines-why-is-it-necessary-to-include-a-backspac
IFS="
"
    declare -n lines=$2
    while read line; do
        lines+=("${line}")
    done <<< "${1}"
}
person Reed    schedule 25.09.2020

Для меня принятый ответ не сработал. Чтобы предотвратить захват

предупреждение: LF будет заменен на CRLF в []. Файл будет иметь исходные окончания строки в вашем рабочем каталоге.

Вместо этого в Powershell я использовал это:

git ls-files -u| ForEach{($_.Split("`t"))|Select-Object -Last 1}| get-unique
person Mariusz    schedule 30.04.2021

небольшой вариант ответа Чарльза Бейли, который дает дополнительную информацию:

git diff --name-only --diff-filter=U | xargs git status
person taj    schedule 04.02.2014

Как указано в других ответах, мы можем просто использовать команду git status, а затем искать файлы, перечисленные в разделе Unmerged paths:

person sandesh    schedule 01.05.2018

person    schedule
comment
Я создал для этого псевдоним: git config --global alias.conflicts "diff --name-only --diff-filter=U" - person Jimothy; 29.03.2013
comment
@CharlesBailey, я что-то упускаю? Что не так с git status? - person Pacerier; 20.10.2015
comment
@Pacerier, это еще хуже. Если бы у вас был миллион неконфликтных слияний и одно конфликтующее слияние, вам потребовалось бы что-то лаконичное для вывода. - person xster; 07.01.2016
comment
@Jimothy, как вы используете этот псевдоним? - person sAguinaga; 12.07.2016
comment
@sAguinaga: просто запустите git conflicts - person Jimothy; 13.07.2016
comment
@QZSupport Вы должны сначала настроить псевдоним, как указано в моем предыдущем комментарии: git config --global alias.conflicts "diff --name-only --diff-filter=U" - person Jimothy; 29.11.2017
comment
@ChristianMatthew diff-filter=U просит показать только файлы, которые не объединены, опция может использовать другие параметры, такие как A для добавленных файлов, M для измененных файлов и так далее. Дополнительную информацию см. В документе: git- scm.com/docs/git-diff#Documentation/ - person Charles Duporge; 27.06.2019
comment
Это продолжает показывать файл даже после разрешения конфликта. git diff --check работает лучше. - person aksanoble; 20.08.2019
comment
Стоит отметить, что это работает только в том случае, если элементы не были поставлены (или не поставлены) после возникновения конфликта. answer (git diff --check) @ cnlevy найдет маркеры конфликтов для неустановленных файлов. - person Amory; 27.02.2020
comment
@Pacerier, на самом деле все в порядке. Но бывают ситуации, когда вам могут понадобиться только имена конфликтующих файлов. Например. команда vim `git diff --name-only --diff-filter=U` откроет все конфликтующие файлы в vim, так что вы можете исправить конфликты один за другим. - person zefciu; 15.04.2020

person    schedule
comment
Примечание. Возможно, вам также придется искать ^ UA и ^ UD, поэтому следующий шаблон будет более полным: ^ U [UAD] - person mda; 11.02.2012
comment
или просто ^U, чтобы все начиналось с U - person Ascherer; 24.01.2014
comment
Этого недостаточно. Конфликтующие файлы могут иметь следующие комбинации: DD, AU, UD, UA, DU, AA, UU - person Anthony Sottile; 14.04.2014
comment
@AnthonySottile: Вы можете объяснить сценарии? Я опубликовал то, что сработало в моем случае. - person mda; 22.06.2014
comment
@mda Один пример: Конфликт, при котором исходный код изменен, который я удалил, будет иметь статус DU - person Anthony Sottile; 22.06.2014
comment
@AnthonySottile, я что-то упустил? Зачем вообще вообще беспокоиться о grep? - person Pacerier; 20.10.2015
comment
Мой вариант использования поддерживал более старые версии git (я полагаю, <1.5), у которых нет опции --diff-filter. - person Anthony Sottile; 20.10.2015
comment
@AnthonySottile, все ли эти комбинации гарантированно конфликтуют, или некоторые из них просто возможно конфликтуют? Изменить: диаграмма по ссылке Матеуша, кажется, указывает на то, что конфликты гарантированы. - person Michael; 14.05.2019
comment
Я не знаю, является ли это кратчайшим регулярным выражением, но оно получает все конфликтующие комбинации и ни одну из конфликтующих комбинаций: grep -E "^([AUD][AU]|[UD]D) ". См. regex101.com/r/Wh1fUi/1. - person Michael; 14.05.2019
comment
@self Также ^(.U|U.|AA|DD). - person Michael; 20.08.2019