Получение списка всех детей данного коммита - PullRequest
8 голосов
/ 10 апреля 2010

Я хотел бы запустить git filter-branch на всех дочерних элементах данного коммита. Это кажется непростой задачей, поскольку, похоже, нет способа сказать git rev-list, что нужно возвращать только детей определенного коммита. Использование синтаксиса .. не будет работать, поскольку оно также будет включать родительские коммиты любого слияния в этом диапазоне. Я что-то здесь упускаю?

редактировать

Чтобы уточнить: у меня есть ветвь с именем base, которая была объединена в derivative несколько раз. Я хотел бы перечислить и в конечном итоге запустить filter-branch, только те коммиты, которые происходят от его самого последнего коммита. Я также хотел бы перечислить похожие коммиты в других ветках.

(упрощенная) ситуация (derivative - ветвь слева):

$ git rev-list --graph --oneline base derivative
*   f16fd151b374b2aeec8b9247489c518a6347d001 merged in the latest from the base branch
|\
| * 564d795afb63eab4ffe758dbcd726ca8b790f9f6 spelling correction
* |   2f2ed5f1d429492e1491740e30be5a58ec20af21 snogg before flarg
|\ \
| |/
| * 0c520ea33ef57b30846b122781d41fcef5e62f9b now with added flarg
* | 5068c34c3862856f511b6b4d48f2adb766e1bde4 now with added snogg
|/
* b51f227e931f830cbda042bc372087398ae7e50d initial commit

@ Предложение Аракнида, похоже, не работает, если я не потрудился прочитать его:

$ git rev-list --oneline derivative --not base
f16fd151b374b2aeec8b9247489c518a6347d001 merged in the latest from the base branch
2f2ed5f1d429492e1491740e30be5a58ec20af21 snogg before flarg
5068c34c3862856f511b6b4d48f2adb766e1bde4 now with added snogg

, поскольку это дает все коммиты в derivative, за исключением коммитов в base. Этот вид имеет смысл, поскольку все, что он делает - это удаляет предков отрицательного коммита. То, что я хочу показать, это только первая строка.

Ответы [ 4 ]

5 голосов
/ 15 июня 2014

Показать пути предков для фиксации A из набора других:

git log--ancestry-path^Aothers

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

git fsck --unreachable --no-reflogs \
| awk '$2 == "commit" {print $3}'

Отслеживание всех потомков коммита A в любом месте репо:

git log --ancestry-path --graph --decorate --oneline ^A \
   --all $(git fsck --unreachable --no-reflogs | awk '$2=="commit" {print $3}')

Показать все ссылки, история которых включает в себя коммит:

git log --ancestry-path --graph --simplify-by-decoration --oneline --all ^A
# and in case A might have a direct ref, add:
git log --ancestry-path --graph --simplify-by-decoration --oneline A^!

править: исправление: не показывать нежелательные коммиты, когда у A есть родители с другими детьми.

5 голосов
/ 10 апреля 2010

хорошо, «--branches» или «--all» будут включать все подсказки ветви, а затем «--not A» исключит A и все его происхождение. Тем не менее, «--branches --not A» будет включать в себя ветви, не содержащие A, что, я думаю, не то, что вам нужно.

Нет простого способа получить все, что вы хотите, хотя вы можете решить это. Это перечислит все ветви, содержащие коммит A:

git for-each-ref refs/heads/* | while read rev type name; do
  git rev-list $rev | grep $(git rev-parse A) >/dev/null && echo $rev
done

тогда вам нужно перечислить все ревизии, доступные для любого из них, но не для самой А и любых ревизий назад

git rev-list $(git for-each-ref refs/heads/* | while read rev type name; do
      git rev-list $rev | grep $(git rev-parse A) >/dev/null && echo $rev
    done) --not A

Обратите внимание, что я только что провёл это очень короткое испытание: p Но я думаю, что основы правильны.

1 голос
/ 23 марта 2017

Я сделал альтернативную версию. Я не знаю, лучше это или хуже.

getGitChildren(){
    git rev-list --all --parents | grep "^.\{40\}.*${1}.*" | awk '{print $1}' | xargs -I commit git log -1 --oneline commit | cat -
}

будет использоваться так:

$ getGitChildren 2e9df93
f210105376 feat(something): did that feature
9a1632ca04 fix(dummy): fix something

Это просто дает список прямых потомков коммита.

0 голосов
/ 11 апреля 2010

Это, кажется, делает это:

$ for rev in $(git rev-list --branches); do
    git rev-list $rev \
      | grep $(git rev-parse base) &>/dev/null \
    && echo $rev;
  done \
  | xargs -L 1 git rev-list -n 1 --oneline
f16fd151b374b2aeec8b9247489c518a6347d001 merged in the latest from the base branch
564d795afb63eab4ffe758dbcd726ca8b790f9f6 spelling correction

Последний раздел канала с xargs просто показывает сообщения о коммитах для каждого из этих коммитов.

Здесь перечисляется целевой коммит в дополнение к его дочерним элементам, что на самом деле и было тем, что я хотел. Тем не менее, он довольно медленный: на репо из 40 коммитов ушло более 3 секунд. Это неудивительно, так как это примерно такая же грубая сила, как и у Андрея Великана. Я предполагаю, что более элегантный метод будет проходить через список оборотов для каждой ссылки и строить дерево хешей каждого коммита, связанного с его потомками, а затем идти по нему, начиная с целевого коммита. Но это довольно сложно, поэтому я надеялся, что для этого была команда git :)

Мне все еще нужно выяснить, как получить этот набор коммитов в filter-branch. Я думаю, я могу просто извлечь rev-list из $GIT_COMMIT из моей команды --tree-filter.

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