Используя Git, покажите все коммиты, которые существуют * только * в одной конкретной ветке, а не * любые * другие - PullRequest
73 голосов
/ 19 апреля 2011

Учитывая ветку, я хотел бы видеть список коммитов, которые существуют только в этой ветке.В этом вопросе мы обсуждаем способы увидеть, какие коммиты находятся в одной ветви, а не в одной или нескольких указанных других ветвях.

Это немного отличается.Я хотел бы видеть, какие коммиты находятся в одной ветви, но не в любых других ветвях.

Вариант использования находится в стратегии ветвления, где некоторые ветви должны только объединяться, и никогдасовершено непосредственно на.Это будет использоваться для проверки того, были ли какие-либо коммиты сделаны непосредственно в ветви «только для слияния».

РЕДАКТИРОВАТЬ: Ниже приведены шаги для установки фиктивного 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

Должна отображаться только фиксация с сообщением «неверная фиксация напрямую только для слияния», которая была сделана непосредственно в ветке только слияния.

Ответы [ 7 ]

66 голосов
/ 14 сентября 2011

Мой коллега только что нашел это элегантное решение git log --first-parent --no-merges. В вашем примере, конечно, начальный коммит все еще обнаруживается.

ПОЖАЛУЙСТА, ПРОЧИТАЙТЕ: этот ответ не совсем отвечает на вопрос, потому что первоначальный коммит все еще отображается. С другой стороны, многие приезжающие сюда, кажется, находят ответ, который ищут. Пожалуйста, примите это во внимание до голосования. Смотрите комментарии для обсуждения.

25 голосов
/ 19 апреля 2011

Предоставлено моим дорогим другом Редмумба :

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)
14 голосов
/ 29 апреля 2016
git log origin/dev..HEAD

Это покажет вам все коммиты, сделанные в вашей ветви.

12 голосов
/ 20 апреля 2011

Может быть, это может помочь:

git show-branch

9 голосов
/ 19 мая 2017

@ Пракаш ответ работает. Просто для наглядности ...

git checkout feature-branch
git log master..HEAD

перечисляет коммиты в ветви функций, но не в ветке upstream (обычно это ваш мастер).

7 голосов
/ 20 апреля 2011

Попробуйте это:

git rev-list --all --not $(git rev-list --all ^branch)

В основном git rev-list --all ^branch получает все ревизии, не входящие в ветку, а затем вы вычитываете все ревизии в репо и вычитаете предыдущий список, который является ревизией только в ветке.

После @ комментариев Брайана:

Из документации git rev-list:

List commits that are reachable by following the parent links from the given commit(s)

Таким образом, команда типа git rev-list A, где A - это коммит, выведет список коммитов, которые достижимы из A, включая A.

Имея это в виду, что-то вроде

git rev-list --all ^A

выведет список коммитов, недоступных из 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), вы получите коммит, который вы искали - "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) даст все коммиты только для слияния.

2 голосов
/ 16 апреля 2012

Еще один вариант принятых ответов, для использования с master

git log origin/master --not $(git branch -a | grep -Fv master)

Фильтровать все коммиты, которые происходят в любой ветке, кроме master.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...