Используя Git, покажите все коммиты, которые находятся в одной ветви, но не в других


465

У меня есть старая ветка, которую я хотел бы удалить. Однако, прежде чем сделать это, я хочу проверить, что все коммиты, сделанные в эту ветку, в какой-то момент были объединены в какую-то другую ветку. Таким образом, я хотел бы видеть все коммиты, сделанные в моей текущей ветке, которые не были применены ни к какой другой ветке [или, если это невозможно без некоторых сценариев, как можно увидеть все коммиты в одной ветке, которые не были применены? в другую данную ветку?].


Чтобы составить список
— Бернд Шуберт,

Ответы:


321

Вы, вероятно, просто хотите

git branch --contains branch-to-delete

Это выведет список всех веток, которые содержат коммиты от "branch-to-delete". Если он сообщает больше, чем просто «ветвь для удаления», ветвь была объединена.

Ваши альтернативы на самом деле просто синтаксис rev-list. например git log one-branch..another-branchпоказывает все что one-branchнужно чтобы все another-branchбыло.

Возможно, вам также будет интересно git show-branchузнать, что и где.



1
Строка «Если он сообщает о чем-то, ветка слилась» может быть неверно истолкована: если git branch --contains some-branchтолько возвращается some-branch, то она возвращает что-то, но она не была объединена.
— Путаница

5
Обратите внимание, что git log foo..barбудут показаны коммиты между последним баром и последним foo, но не будут зафиксированы другие коммиты, отсутствующие в более отдаленном времени Чтобы увидеть все в баре, но не в foo, вы должны использовать решение @ jimmyorr.
— Paul A Jungwirth

557

Чтобы увидеть список коммитов в одной ветви, но не в другой, используйте git log:

git log --no-merges oldbranch ^newbranch

... то есть показать логи коммитов для всех коммитов на oldbranch, которые не на newbranch. Вы можете перечислить несколько веток для включения и исключения, например,

git log  --no-merges oldbranch1 oldbranch2 ^newbranch1 ^newbranch2

Примечание: в Windows ^это escape-ключ, поэтому его нужно экранировать другим ^:

git log --no-merges oldbranch ^^newbranch

2
Я нашел это в поисках git Compare коммитов двух веток.
— Пользователь

25
Это именно то, что я искал. Но использование здесь ^в качестве префикса меня смутило. В этом контексте это означает исключить эту ветвь. Использование ^в качестве суффикса будет относительной ссылкой на родительский коммит этой ветви.
— Джо Флинн

4
очень полезное спасибо. Мне любопытно, зачем нужен флаг --no-merges? Конечно, кто-то хочет увидеть эти коммиты тоже?
— Макс МакЛауд

2
Хотите использовать Gitk с этим? Просто используйте gitk oldbranch ^newbranch --no-merges(протестировано с git 1.8.1.1). Дополнительное примечание, для меня ^означает включающий HEAD коммит ветви newbranch.
— Мэтт

2
@NazariiGudzovatyi - да, есть: "-cherry-pick". Существует огромное количество опций для входа на странице документации
— romeara

91

Чтобы показать коммиты в oldbranch, но не в newbranch:

git log newbranch..oldbranch

Чтобы показать разницу по этим коммитам (обратите внимание, что есть три точки):

git diff newbranch...oldbranch

Вот документ с иллюстрацией диаграммы https://git-scm.com/book/en/v2/Git-Tools-Revision-Selection#Commit-Ranges


См . Комментарий Пола А Юнгвирта выше. Кажется, это пропустит некоторые старые коммиты?
— Унылая переменная

2
Я не уверен, что означают старые коммиты. Двойные точки в основном просят Git разрешить диапазон коммитов, которые доступны из одного коммита, но недоступны из другого. Вот документ с иллюстрацией диграммы git-scm.com/book/en/v2/…
— Сюань

1
и если мы на или newbranchили oldbranch, мы можем сделать git log ..oldbranchили git log newbranch..соответственно
— YakovL

Решение jimmyorr не сработало для меня, но это сработало благодаря двум точкам ..между именами судей. Я также использовал --cherry-pickопцию, чтобы скрыть коммиты, которые присутствуют в обеих ветвях, но имеют разные хэши, потому что они выбирались из одной ветви в другую.
— flawyte

58

Для тех, кто все еще ищет простой ответ, проверьте git cherry . Он сравнивает фактические различия вместо хешей коммитов. Это означает, что он принимает коммиты, которые были выбраны или перебраны вишней.

Сначала оформите ветку, которую хотите удалить:

git checkout [branch-to-delete]

затем используйте git cherry, чтобы сравнить его с вашей основной веткой разработки:

git cherry -v master

Пример вывода:

+ 8a14709d08c99c36e907e47f9c4dacebeff46ecb Commit message
+ b30ccc3fb38d3d64c5fef079a761c7e0a5c7da81 Another commit message
- 85867e38712de930864c5edb7856342e1358b2a0 Yet another message

Примечание. -vФлаг должен включать сообщение о фиксации вместе с хешем SHA.

Строки с '+' находятся в ветви для удаления, но не в главной ветви. Те, у кого впереди символ «-», имеют эквивалентный коммит в master.

Для просто коммитов, которых нет в master, объедините вишневый кир с grep:

git cherry -v master | grep "^\+"

Пример вывода:

+ 8a14709d08c99c36e907e47f9c4dacebeff46ecb Commit message
+ b30ccc3fb38d3d64c5fef079a761c7e0a5c7da81 Another commit message

Я пробовал это, но он все еще сообщает, что есть много коммитов в fb (функциональная ветвь), которых нет в mb (основная ветвь). Однако, если я нахожусь в fb и делаю git diff mb, я не вижу различий. Я использовал rebase и раздавил все. Я почти уверен, что именно поэтому, но я просто хочу быть уверен. Если это так, то я буду избегать раздавливания, если это вообще возможно; Я нахожусь в "информационном лагере без потерь". Интересно, можно ли было бы добавить режим отображения журнала, который может отображать слияния, как если бы они были перебазированием, чтобы сохранить историю в чистоте и при этом не потерять информацию.
— Outis Von Nemo

1
Не уверен в вашем точном сценарии здесь, но если вы сложили несколько коммитов в один и сравнили это с другой веткой, где коммиты раздельные, это определенно не сработает. В этом случае вы можете просто использовать diffутилиту unix для сравнения различных файлов. Или вы можете создать временную ветку и раздавить все коммиты в том же порядке, что вы делали с оригинальной веткой, а затем использовать это, что, я думаю, будет работать.
— Тим С

50

Хотя некоторые ответы, опубликованные здесь, помогут найти то, что вы ищете, следующая подкоманда git branch - более подходящее решение для вашей задачи.

--merged используется для поиска всех ветвей, которые можно безопасно удалить, поскольку эти ветви полностью содержатся в HEAD.

В то время как в masterодном можно запустить команду для перечисления ветвей, которые можно безопасно удалить, например, так:

git branch --merged
  develop
  fpg_download_links
* master
  master_merge_static

# Delete local and remote tracking branches you don't want
git branch -d fpg_download_links
git push origin :fpg_download_links
git branch -d master_merge_static
git push origin :master_merge_static

# There is also a flag to specify remote branches in the output
git branch --remotes --merged

16

Ответ jimmyorr не работает на Windows. это помогает использовать --notвместо ^так:

git log oldbranch --not newbranch --no-merges

4
Это правильно, +1. Обратите внимание , однако , что ^поддерживается на Windows, но нужно экранировать, что, в Windows, есть (другой) ^: git log oldbranch ^^newbranch --no-merges.
— VonC

3
В частности, он работает в Windows в консоли Powershell, но требует дополнительного «^» в CMD.
— Род

7

Если вам нужно проверить одну (одну) ветку, например, если вы хотите, чтобы эта ветка 'B' была полностью объединена с веткой 'A', вы можете просто сделать следующее:

$ git checkout A
$ git branch -d B

git branch -d <branchname> имеет безопасность: «Ветвь должна быть полностью объединена в ГОЛОВУ».

Внимание : это фактически удаляет ветвь B, если она объединена с A.


3

Вы можете использовать этот простой скрипт, чтобы увидеть коммиты, которые не объединены

#!/bin/bash
# Show commits that exists only on branch and not in current
# Usage:
#   git branch-notmerge <branchname>
#
# Setup git alias
#   git config alias.branch-notmerge [path/to/this/script]
grep -Fvf <(git log --pretty=format:'%H - %s') <(git log $1 --pretty=format:'%H - %s')

Вы также можете использовать инструмент git-wtf, который будет отображать состояние веток


0

Просто используйте, git cherryчтобы выбрать все коммиты в веткеnewFeature42 например:

git cherry -v master newFeature42


-5

Начните создавать запрос на извлечение помощью используемого вами хостинга git. Если ветвь полностью объединена с базовой веткой, вы не сможете создать новый PR.

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

Например, на GitHub:

Не с чем сравнивать

Не удается создать пиар для филиалов, которые были объединены.

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

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.