Как узнать, какие коммиты в одной ветке отсутствуют в другой?

180

У меня есть две ветви develи next. В devel у меня более или менее огромное количество коммитов. Некоторые из коммитов выбраны из вишни next. Также я добавил несколько коммитов к следующему, которые объединены с devel.

Теперь я хотел бы увидеть, чего не хватает next, чтобы я мог подробно протестировать изменения, прежде чем вносить их next. Мой вопрос сейчас, как я могу увидеть, какие коммиты есть, develа какие нет?

Саша Эфферт
источник
Ваш заголовок немного вводит в заблуждение, так как вы хотите сравнить это верхушка обеих ветвей. и я пришел сюда в поисках решения для сравнения двух конкретных (разных)
коммитов
Дублировать ?: stackoverflow.com/questions/1710894/…
reinierpost

Ответы:

210

Маленькая команда git cherryпоказывает вам коммиты, которые еще не были выбраны. Документация git cherryнаходится здесь , но, в общем, вы просто должны быть в состоянии сделать:

git checkout devel
git cherry next

... и посмотреть вывод примерно так:

+ 492508acab7b454eee8b805f8ba906056eede0ff
- 5ceb5a9077ddb9e78b1e8f24bfc70e674c627949
+ b4459544c000f4d51d1ec23f279d9cdb19c1d32b
+ b6ce3b78e938644a293b2dd2a15b2fecb1b54cd9

Коммиты, которые начинаются с +тех, которые вы еще не выбрали next. В этом случае, я бы выбрал только один вишневый коммит. Возможно, вы захотите добавить -vпараметр в git cherryкоманду, чтобы он также выводил строку темы каждого коммита.

Марк Лонгэйр
источник
Отлично, это то, что мне было нужно. Также было бы неплохо получить краткое описание тестов, но я могу написать это.
Саша Эфферт
29
Вам не нужно git checkout devel, вы можете просто сделать git cherry next devel.
Робин Уинслоу
21
«Может быть, хотите добавить -v» ? Вишня без, -vкак lsбез -la. ; -J
Слипп Д. Томпсон
1
И вы не знаете, как cherryпометить или исключить эквивалентные коммиты? cherryпохоже на сантехническую команду, но не предлагает (кажется) много вариантов. То, что я сейчас нахожусь в центре, git cherryдает мне ложные срабатывания, но @ sehe's git log --cherry-pickправильно исключает ранее выбранные / перебазированные коммиты.
Слипп Д. Томпсон
Документация содержит конкретный пример: git-scm.com/docs/git-cherry#_concrete_example
ams
107

Также вы можете использовать

git log --left-right --graph --cherry-pick --oneline devel...next

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

Оперативное слово --cherry-pick

--cherry-pick

Опустите любой коммит, который вносит то же изменение, что и другой коммит на «другой стороне», когда набор коммитов ограничен симметричной разностью. Например, если у вас есть две ветви, A и B, обычным способом перечисления всех коммитов только на одной их стороне является --left-right, как в примере выше в описании этой опции. Однако он показывает коммиты, которые были выбраны вишней из другой ветви (например, «3-е на b» может быть выбрано вишней из ветви A). С помощью этой опции такие пары коммитов исключаются из вывода.

Обновить Как упоминалось в комментарии, добавлены последние версии git --cherry-mark:

--cherry-mark

Подобно --cherry-pick (см. Ниже), но помечать эквивалентные коммиты с помощью =, а не пропускать их, и неэквивалентные с +.

sehe
источник
1
Это не сработало для меня. Моя версия git не знает - one-line, поэтому я удалил ее. Затем мне пришлось обменять devel на следующий и все заработало. Очень хорошо!
Саша Эфферт
@SaschaEffert: вам не нужно было переключать devel и next (обратите внимание на ТРИ точки, а не ДВА). Тем не менее, все может быть иначе, если вы использовали древнюю версию git (?), Но в этом случае вы должны были получить ошибку rev-parse для трех точек.
sehe
2
Для забавы я выяснил, что синтаксис пересмотра '...' (симметричное различие) был добавлен в июле 2006 года , а документация для него была обновлена ​​в июне 2008 года . Радость с открытым исходным кодом!
sehe
1
'gls --first-parent --cherry-mark --left-onlyvelop ... next', где gls - это мой псевдоним журнала git со всем приятным форматированием. Вишневый знак показывает, что и вишневый, и не вишневый коммиты развиваются, но помечают их по-разному.
angularsen
1
добавить --no-
merges
51

Вы можете попробовать сделать подмножества журнала git:

git log --oneline devel ^next
Брайан Бакли
источник
4
На мой взгляд, это лучшее решение (ответ @ sehe также показывает коммиты в следующем, которых нет в devel - в контексте OP их нет, но в моем есть - использование --left-onlyбыло бы лучше). Тем не менее, этот можно немного улучшить, добавив, --no-mergesчтобы пропустить любые коммиты слияния (например, если функция или ветвь исправления были объединены (отдельно) как в devel, так и в next). Строго говоря, конечно, разрешение конфликтов в слияниях может создавать другие различия, но обычно это не так. --no-mergesВариант может быть успешно применен для других ответов , а также.
Алекс Дюпуй
27

Как насчет

git log next..devel

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

justingordon
источник
4
Вы также можете опустить вторую ветку, если вы в данный момент находитесь на этой ветке. т.е.git log next..
jmaxyz
Кстати, «git log next..devel» отличается от «git log devel..next»
Евгений Кауров
1

Чтобы получить список коммитов, которые не были интегрированы в ветку релиза (далее), вы можете использовать:

git rev-list --reverse --pretty="TO_TEST %h (<%ae>) %s" --cherry-pick --right-only origin/release_branch...origin/development_branch | grep "^TO_TEST " > NotIntegratedYet.txt

Проверьте git-rev-list для получения дополнительной информации.

Михай
источник
в команде этого ответа отсутствуют актуальные ветви, о которых идет речь, т. е.next...devel
Алекс Дюпюи
@AlexDupuy Да, это довольно недоделанный ответ. Так как это тоже не самый простой ответ и не объясняет , почему этот подход был бы лучше, я -1 -ную его.
Слипп Д. Томпсон
-1

@Mark Longair прибил это в своем ответе здесь , но я хотел бы добавить некоторую дополнительную информацию.

Связанный и отвечающий на вопрос о том, как разбить большой запрос на извлечение (PR), особенно когда сжатие ваших коммитов нецелесообразно из-за одного или нескольких слияний мастера в ваш feature_branch

Моя ситуация:
я заработал feature_branch30 коммитов и открыл запрос на извлечение (PR) на GitHub, чтобы объединить его master. Филиал masterизменил тонну подо мной и получил 200 коммитов, которых у меня feature_branchне было. Чтобы разрешить конфликты, которые я сделал, git checkout feature_branchи git merge masterобъединить masterизменения в свои feature_branch. Я предпочел, mergeа не потому, что это может стереть историю комментариев GitHub в PR. Итак, я слил master в свою ветку функций и разрешил конфликты один раз. Все было хорошо. Мой PR, однако, был слишком большим для моих коллег, чтобы рассмотреть. Мне нужно было разделить это. Я пошел, чтобы раздавить мои 30 коммитов и ОН НЕТ! ГДЕ ОНИ? ОНИ ВСЕ ЗАПРЕЩЕНЫ с 200 недавними коммитами, потому что я слился с моимrebase последнего мастера, поэтому мне придется разрешать конфликты только один раз, а не 30 раз (по одному разу для каждого из моих коммитов). Я не хотел сначала раздавить свои 30 коммитов в 1, а затем перенести на последнийmastermastermasterfeature_branch! ЧТО МНЕ ДЕЛАТЬ?

git cherryиспользование в случае, если вы хотите попробовать git cherry-pickотдельные коммиты:

git cherry на помощь (вроде)!

Чтобы увидеть все коммиты, которые находятся в, feature_branchно НЕ в masterя могу сделать:

git checkout feature_branch
git cherry master

ИЛИ, я могу проверить коммиты из ЛЮБОГО ветвления с ВНИМАНИЕМ, гарантируя, что я feature_branchпервым делаю git cherry [upstream_branch] [feature_branch], как это. Опять же, это проверяет, какие коммиты есть, feature_branchно нет upstream_branch( masterв этом случае):

git cherry master feature_branch

Добавление -vтакже показывает строки темы сообщения о коммите:

git cherry -v master

Трубопровод к «подсчету слов» «-lines» ( wc -l) подсчитывает, сколько существует коммитов :

git cherry master | wc -l

Вы можете сравнить это количество с номером коммита, показанным в вашем GithHub PR, чтобы почувствовать себя лучше, зная, что он git cherryдействительно работает. Вы также можете сравнить git-хэши один за другим и посмотреть, совпадают ли они с git cherryGitHub. Обратите внимание , что git cherryне будет рассчитывать любые слияния фиксаций, вы слиты masterв feature_branch, но GitHub ВОЛЯ. Так что, если вы видите небольшое расхождение в подсчете, поищите на странице коммита GitHub PR слово «слияние», и вы, вероятно, увидите, что это виновник, которого не видно git cherry. Пример: коммит под названием «Объединить ветку 'master' в feature_branch" будет отображаться в GitHub PR, но не при запуске git cherry master feature_branch. Это нормально и ожидаемо.

Итак, теперь у меня есть способ выяснить, какие различия я хочу выбрать из вишни на новую ветку функций, чтобы разделить эту разницу: я могу использовать git cherry master feature_branchлокально или посмотреть коммиты в GitHub PR.

Как может помочь раздавливание - если бы мы только могли раздавить:

Однако, чтобы разделить мой большой дифференциал, нужно разделить все 30 моих коммитов на один, залатать их в новую ветвь функций, мягко сбросить коммит патча, а затем использовать git guiдля добавления фрагментов файл за файлом, кусок за кусок или построчно. Как только я получу одну подфункцию, я могу зафиксировать то, что я добавил, затем проверить новую ветку, добавить еще несколько, зафиксировать, проверить новую ветку и т. Д., Пока моя большая функция не будет разбита на несколько подфункций. , Проблема в том, что мои 30 коммитов смешаны с другими 200 коммитами от других людей из-за моего git merge masterв мой feature_branch, поэтому перебазировка нецелесообразна, так как мне пришлось бы просеять 230 коммитов, чтобы переупорядочить и раздавить мои 30 коммитов.

Как использовать файл патча как гораздо более простую замену сквошу:

Обходной путь - просто получить файл патча, содержащий «эквивалент сквоша» из всех 30 моих коммитов, патчить его на новый masterветвь (новую ветвь подфункции) и работать оттуда следующим образом:

git checkout feature_branch
# ensure I have the latest changes from master merged into feature_branch
git merge master 
# Obtain a patch file, which is the equivalent of a squash of my 30 commits into 1 commit:
git diff master..feature_branch > ~/mypatch.patch
git checkout master
# Create a new, sub-feature branch
git checkout -b feature_branch2
# Patch the 30 commit patch file onto it:
git apply ~/mypatch.patch

Теперь у меня есть 30-коммитный патч, примененный локально, но без изменений и без изменений.

Теперь используйте, git guiчтобы добавить файлы, чанки и / или строки и разбить ваш большой PR или «diff»:

Обратите внимание, что если у вас его нет git gui, вы можете легко установить его в Ubuntu с помощью sudo apt install git-gui.

Теперь я могу запустить git guiи начать добавлять файлы, чанки и / или строки (щелкнув правой кнопкой мыши в программе git GUI), и разбить ветвь функции 30 коммитов на подветви, как описано выше, многократно добавляя, фиксируя, затем разветвляясь ветвь новой функции и повторение этого цикла, пока все изменения не будут добавлены в ветку подфункции, и моя функция 30 коммитов успешно разбита на 3 или 4 подфункции. Теперь я могу открыть отдельный PR для каждой из этих подфункций, и моей команде будет легче их просматривать.

Ссылки:

  1. Создайте файл патча или diff из репозитория git и примените его к другому другому репозиторию git
Габриэль Стейплс
источник
Мне нужно было сослаться на этот ответ сегодня, но я не смог найти его быстро. К счастью, у него было понижающее голосовое давление, чтобы помочь мне найти его проще, поэтому простой щелчок по значку кубка с наградами в правом верхнем углу экрана показал, где я недавно потерял 2 очка, и щелчок по нему вернул меня сюда, где я могу Теперь сослаться на мой собственный ответ здесь! Надеюсь, я больше не получаю отрицательных отзывов, но даунвотеру, спасибо за услугу, которая случайно помогла мне!
Габриэль Стейплс