Используя 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)
даст все фиксация только в слиянии.