Как проверить слияние без фактического слияния
Есть ли способ имитации git merge
между двумя ветками, текущей рабочей веткой и мастером, но без внесения каких-либо изменений?
У меня часто возникают конфликты, когда я должен сделать git merge
, Есть ли способ имитации слияния в первую очередь?
9 ответов
Я не думаю, что есть способ имитировать то, что произойдет, пока вы не попробуете слияние. Однако, если вы убедитесь, что на выходе git status
пусто до того, как вы сделаете слияние, вполне безопасно просто пойти и попробовать. Если у вас возникли конфликты, вы можете немедленно вернуться в состояние, в котором вы были раньше:
git reset --merge
Начиная с git 1.7.4, вы также можете прервать слияние, выполнив:
git merge --abort
(Как объясняется в сообщении о фиксации, добавляющем эту опцию, это было добавлено для соответствия git rebase --abort
и так далее.)
Ты можешь использовать git merge --no-commit
чтобы предотвратить слияние на самом деле, и если вам не нравится, как слияние происходит, просто верните исходную головку.
Если вы определенно не хотите завершать слияние, даже если это ускоренная перемотка (и, следовательно, по определению не имеет конфликтов), вы можете добавить --no-ff
также.
Если я хочу сравнить изменения в ветке темы с master, я считаю, что проще и безопаснее сделать следующее:
git checkout master
git checkout -b trial_merge
git merge topic_branch
После завершения слияния легко увидеть консолидированное изменение из основного
git diff master
Когда закончите, просто удалите ветвь trial_merge
git checkout master
git branch -D trial_merge
Таким образом, основная ветвь никогда не меняется.
Вот решение, которое я нашел:
git merge-tree
выполняет слияние "в памяти" и печатает разницу, не касаясь вашего рабочего каталога. Вы даже можете протестировать ветку, не проверяя ее.
Получите разницу слияния
Сначала сделайте это, чтобы убедиться, что ваш репозиторий знает обо всех удаленных ветках:
$ git fetch --all
Теперь используйте этот фрагмент bash, чтобы увидеть, как ветвь
$branch
будет сливаться в
$master
:
$ branch='feature'
$ git merge-tree $(git merge-base $branch master) master $branch
В ваш рабочий каталог или индекс не вносятся изменения. Это пробное слияние.
Выберите информацию из вывода
На выходе получается разница. Если ветка была объединена, она будет пустой.
Чтобы узнать, есть ли конфликты, используйте grep для
<<<
:
$ git merge-tree $(git merge-base $branch master) master $branch | fgrep '<<<'
Чтобы извлечь различия конфликтов, используйте
sed
извлекать строки между
<<<
и
>>>
:
$ git merge-tree $(git merge-base $branch master) master $branch | \
sed -ne '/^\+<<</,/^\+>>>/ p'
Особенности
- Разница будет пуста, если ветка уже объединена
- Используйте grep/sed для извлечения информации о конфликтах
- Использовать
origin/feature
для тестирования веток, с которыми вы никогда не работали - Может использоваться, чтобы увидеть, как две ветви разошлись
Добавить в избранное
Получите разницу слияния:
git config --global alias.mergediff '!f(){branch= "$ 1"; в ="$2"; git merge-tree $(git merge-base "$branch" "$into") "$into" "$branch"; };f '
Применение:
$ git mergediff <feature-branch> <merge-into>
$ git mergediff feature master
Получите конфликты слияния:
git config --global alias.mergetest '!f(){git mergediff $@ | sed -ne "/ ^ +<<< /,/^+>>>/ p"; };f '
Применение:
$ git mergetest <feature-branch> <merge-into>
$ git mergetest feature master
Почему бы просто не создать одноразовую ветку (git checkout -b) и выполнить там тестовое слияние?
Я использую:
git merge --ff-only
согласно документации:
Отказаться от слияния и выхода с ненулевым статусом, если текущий HEAD уже не обновлен или слияние не может быть разрешено как ускоренная перемотка вперед.
Это на самом деле не симуляция, потому что произойдет ускоренное слияние в случае отсутствия конфликтов между двумя ветвями. Но в случае конфликтов вы будете проинформированы и ничего не произойдет.
Я был в состоянии использовать git merge --abort
, относительно недавно. Однако это можно использовать только в случае конфликта слияния. Если вы уверены, что не захотите совершать коммит, используйте другие упомянутые выше методы.
Я хотел бы добавить к превосходному ответу @kolypto - (это должен быть комментарий, но у меня нет баллов).
На странице руководства в разделе «Ошибки, которых следует избегать» указано:
НЕ просматривайте полученное дерево верхнего уровня, чтобы попытаться определить, какие файлы конфликтуют [...] существует множество типов конфликтов, которые не могут быть представлены маркерами конфликта (изменение/удаление, конфликт режимов, двоичный файл изменен с обеих сторон, конфликты файлов/каталогов). , различные варианты конфликтов переименований и т. д.)
...так что делаю
Для успешного слияния без конфликтов статус выхода равен 0. Если слияние имеет конфликты, статус выхода равен 1. Если слияние не может быть завершено (или запущено) из-за какой-либо ошибки, статус выхода равен 1. что-то отличное от 0 или 1 (и результат не указан).
Пример:
#!/bin/bash
branch='myFeatureBranch'
ret=0
mergeTest=`git merge-tree --write-tree master $branch` || ret=$?
if [ ! $ret -eq 0 ];then
echo "Merge would result in conflicts:"
echo "$mergeTest" | grep CONFLICT
## Do something useful here
exit 1
fi
Я не знаю точно, относится ли это к вашему делу, но ваш вопрос помните, что иногда я запускаю функцию, я фиксирую ее в течение нескольких дней и объединяю разработку с ней много раз.
На этом этапе я теряю контроль над точными файлами, которые я изменил, и я буду знать это только тогда, когда моя функция будет закрыта и мой код будет разрабатываться.
В этом случае, хороший способ узнать, какие изменения вы сделали (а не какие-либо из слияний), использует Sourcetree.
Вы должны щелкнуть правой кнопкой на базовой ветви и выбрать Diff Against Current
:
Затем sourcetree покажет вам все модификации, которые будут объединены, если вы объедините свою ветку с базовой веткой.
Конечно, это не покажет вам конфликты, но это полезный инструмент в слияниях.