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

465

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

sircolinton
источник
Чтобы составить список
Бернд Шуберт,
Связанный: stackoverflow.com/q/1419623/1959808
Иоаннис Филиппидис

Ответы:

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узнать, что и где.

Dustin
источник
2
+1. См. Также stackoverflow.com/questions/850607/…
VonC
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
jimmyorr
источник
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
sebeck
источник
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, который будет отображать состояние веток

Manro
источник
0

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

git cherry -v master newFeature42

Mꜳltus
источник
-5

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

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

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

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

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

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

pkamb
источник