Попробуйте это:
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)
даст все коммиты только для слияния.