Используя Git, покажите все коммиты, которые существуют *только* на одной конкретной ветке, а не *любые* другие
учитывая ветку, я хотел бы видеть список коммитов, которые существуют только на этой ветке. В этом вопросе мы обсуждаем способы увидеть, какие коммиты находятся на одной ветви, но не на одной или нескольких указанных других ветвях.
Это немного отличается. Я хотел бы видеть, какие коммиты находятся на одной ветке, но не на любой другие филиалы.
вариант использования находится в стратегии ветвления, где некоторые ветви должны быть только объединены и никогда не фиксируются прямо сейчас. Это будет использоваться для проверки того, были ли какие-либо фиксации сделаны непосредственно в ветке "только слияние".
EDIT: Ниже приведены шаги по настройке фиктивного РЕПО git для тестирования:
git init
echo foo1 >> foo.txt
git add foo.txt
git commit -am "initial valid commit"
git checkout -b merge-only
echo bar >> bar.txt
git add bar.txt
git commit -am "bad commit directly on merge-only"
git checkout master
echo foo2 >> foo.txt
git commit -am "2nd valid commit on master"
git checkout merge-only
git merge master
должна отображаться только фиксация с сообщением "bad commit непосредственно на merge-only", которая была сделана непосредственно на ветке merge-only.
7 ответов:
мой коллега только что нашел это элегантных решение
git log --first-parent --no-merges. В вашем примере, конечно, начальная фиксация все еще появляется.пожалуйста, прочитайте: этот ответ не совсем отвечает на вопрос, потому что начальная фиксация все еще отображается. С другой стороны, многие люди, приезжающие сюда, похоже, находят ответ, который они ищут. Пожалуйста, рассмотрите это перед голосованием вниз. См. комментарии для обсуждения.
любезность моего дорогого друга Redmumba:
git log --no-merges origin/merge-only \ --not $(git for-each-ref --format="%(refname)" refs/remotes/origin | grep -Fv refs/remotes/origin/merge-only)...где
origin/merge-only- это ваше удаленное имя ветви только для слияния. Если вы работаете с локальным РЕПО git, заменитеrefs/remotes/originСrefs/heads, и заменить имя удаленного филиалаorigin/merge-onlyС именем локальной ветвиmerge-only, например:git log --no-merges merge-only \ --not $(git for-each-ref --format="%(refname)" refs/heads | grep -Fv refs/heads/merge-only)
попробуйте это:
git rev-list --all --not $(git rev-list --all ^branch)в принципе
git rev-list --all ^branchполучает все ревизии не в ветке, а затем вы все ревизии в репо и вычитаете предыдущий список, который является ревизиями только в филиале.после комментариев @ Brian:
из документации git rev-list:
List commits that are reachable by following the parent links from the given commit(s)так что команда вроде
git rev-list Aгде A-это фиксация, будет список коммитов, которые доступны из A включительно А.имея это в виду, что-то вроде
git rev-list --all ^Aбудет список коммитов, недоступных из
так
git rev-list --all ^branchперечислит все коммиты, недоступные из кончика ветви. Который удалит все коммиты в ветке, или другими словами коммиты, которые находятся только в других ветвях.теперь давайте перейдем к
git rev-list --all --not $(git rev-list --all ^branch)это будет как
git rev-list --all --not {commits only in other branches}Итак, мы хотим перечислить
all, что не доступно изall commits only in other branchesкоторый является набором коммитов, которые только в филиала. Возьмем простой пример:
master | A------------B \ \ C--------D--------E | branchздесь цель состоит в том, чтобы получить D и E, коммиты не в любой другой ветке.
git rev-list --all ^branchдайте только Bтеперь
git rev-list --all --not Bэто то, к чему мы пришли. Что тожеgit rev-list -all ^B- мы хотим, чтобы все коммиты были недоступны из B. В нашем случае это D и E. Это то, что мы хотим.надеюсь, что это объясняет, как команда работает правильно.
редактировать после комментария:
git init echo foo1 >> foo.txt git add foo.txt git commit -am "initial valid commit" git checkout -b merge-only echo bar >> bar.txt git add bar.txt git commit -am "bad commit directly on merge-only" git checkout master echo foo2 >> foo.txt git commit -am "2nd valid commit on master"после вышеуказанных шагов, если вы делаете
git rev-list --all --not $(git rev-list --all ^merge-only)вы получите фиксацию, которую вы искали-the"bad commit directly on merge-only"один.но как только вы сделаете последний шаг в шагах
git merge masterкоманда не даст ожидаемого результата. Потому что на данный момент нет фиксации, которой нет в слиянии-только с тех пор, как одна дополнительная фиксация в master также была объединена только для слияния. Так чтоgit rev-list --all ^branchдает пустой результат, и, следовательно,git rev-list -all --not $(git rev-list --all ^branch)даст все фиксация только в слиянии.