Как найти следующую фиксацию в git? (ребенок / дети)

ref^ ссылается на фиксацию до ref , как насчет получения фиксации после ref ?

Например, если я git checkout 12345 как я могу проверить следующую фиксацию?

Благодарю.

PS Да, git – это указатель узла DAG struct tree. Как найти коммит после этого?

Чтобы перечислить все коммиты, начиная с текущего, а затем с его дочернего элемента и т. Д. – в основном стандартный журнал git, но вовремя, используйте что-то вроде

 git log --reverse --ancestry-path 894e8b4e93d8f3^..master 

где 894e8b4e93d8f3 – это первая фиксация, которую вы хотите показать.

Создатель для Хадсона (теперь Дженкинс) Кохсуке Кавагути только что опубликовал (ноябрь 2013 года):
kohsuke / git-children-of :

Учитывая фиксацию, найдите непосредственных детей из этой фиксации.

 #!/bin/bash -e # given a commit, find immediate children of that commit. for arg in "[email protected]"; do for commit in $(git rev-parse $arg^0); do for child in $(git log --format='%H %P' --all | grep -F " $commit" | cut -f1 -d' '); do git describe $child done done done 

Как проиллюстрировано этим streamом , в VCS, основанной на истории, представленной DAG (Directed Acyclic Graph) , нет «одного родителя» или «одного ребенка».

  C1 -> C2 -> C3 / \ A -> BE -> F \ / D1 -> D2 ----/ 

Порядок коммитов выполняется с помощью «topo-order» или «date-order» (см. Книгу GitPro )

Но с Git1.6.0 вы можете перечислить дочерние элементы коммита.

 git rev-list --children git log --children 

Примечание: для родительских коммитов у вас есть та же проблема, с суффиксом ^ с параметром ревизии, означающим первого родителя этого объекта commit. ^ означает th родительский (т. е. rev^ эквивалентен rev^1 ).

Если вы находитесь в ветке foo и задаете « git merge bar », тогда foo будет первым родителем.
Т.е.: первым родителем является ветка, в которой вы были включены, когда вы слились, а вторая – фиксация на ветке, в которую вы слились.

что я нашел

 git rev-list --ancestry-path commit1..commit2 

где я устанавливаю commit1 как текущую фиксацию и commit2 текущей голове. Это возвращает мне список всех commit1 которые строят путь между commit1 и commit2 .

Последней строкой вывода является дочерний элемент commit1 (по пути к commit2).

Не существует уникальной «следующей фиксации». Поскольку история в Git – это DAG, а не строка, многие коммиты могут иметь общий родительский элемент (ветви), а commits может иметь более одного родителя (слияния).

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

Я знаю, что Вы имеете ввиду. Это разочаровывает наличие большого синтаксиса для перехода к предыдущим фиксациям, но ни один из них не подходит к следующим. В сложной истории проблема «что является следующей фиксацией» становится довольно сложной, но тогда в сложном слиянии такая же твердость возникает и с «предыдущими» фиксациями. В простом случае внутри одной ветви с линейной историей (даже локально для некоторого ограниченного количества коммитов) было бы неплохо и иметь смысл идти вперед и назад.

Реальная проблема с этим, однако, заключается в том, что дети не фиксируются, это только список, связанный с обратной связью. Поиск child commit принимает поиск, что не так уж плохо, но, вероятно, не что-то git хочет вставить в логику refspec.

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

Выберите фиксацию перед тем, где вы находитесь. Вероятно, это может быть ветка. Если вы находитесь в ветке ~ 10, тогда “git checkout branch ~ 9”, затем “git checkout branch ~ 8”, чтобы получить следующий после этого, затем “git checkout branch ~ 7” и так далее.

Сокращение числа должно быть очень простым в сценарии, если вам это нужно. Намного проще, чем разобрать git rev-list.

В случае, когда у вас нет конкретной цели «назначения», но вместо этого вы хотите видеть, что дочерние фиксации могут находиться в любой ветви, вы можете использовать эту команду:

 git rev-list --children --all | grep ^${COMMIT} 

Если вы хотите увидеть всех детей и внуков , вы должны использовать rev-list --children рекурсивно, например:

 git rev-list --children --all | \ egrep ^\($(git rev-list --children --all | \ grep ^${COMMIT} | \ sed 's/ /|/g')\) 

(Версия, которая дает только grand-children, будет использовать более сложный sed и / или cut .)

Наконец, вы можете log --graph команду log --graph чтобы увидеть древовидную структуру, например:

 git log --graph --oneline --decorate \ \^${COMMIT}^@ \ $(git rev-list --children --all | \ egrep ^\($(git rev-list --children --all | \ grep ^${COMMIT} | \ sed 's/ /|/g')\)) 

Два практических ответа:

Один ребенок

Основываясь на ответе @ Michael , я взломал child псевдоним в моем .gitconfig .

Он работает как ожидалось в случае по умолчанию, а также универсален.

 # Get the child commit of the current commit. # Use $1 instead of 'HEAD' if given. Use $2 instead of curent branch if given. child = "!bash -c 'git log --format=%H --reverse --ancestry-path ${1:-HEAD}..${2:\"$(git rev-parse --abbrev-ref HEAD)\"} | head -1' -" 

По умолчанию он задает дочерний элемент HEAD (если не указан другой аргумент commit-ish), следуя за родословной на один шаг к кончику текущей ветви (если только другой commit-ish не указан как второй аргумент).

Используйте %h вместо %H если вы хотите короткую hash-форму.

Несколько детей

С отдельной головой (нет ветки) или для того, чтобы получить всех детей независимо от их ветвей:

 # For the current (or specified) commit-ish, get the all children, print the first child children = "!bash -c 'c=${1:-HEAD}; set -- $(git rev-list --all --not \"$c\"^@ --children | grep $(git rev-parse \"$c\") ); shift; echo $1' -" 

Измените $1 на $* чтобы распечатать всех детей

У меня есть этот псевдоним в ~/.gitconfig

 first-child = "!f() { git log --reverse --ancestry-path --pretty=%H $1..${2:-HEAD} | head -1; }; f" 

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

найти следующую фиксацию

 function n() { git log --reverse --pretty=%H master | grep -A 1 $(git rev-parse HEAD) | tail -n1 | xargs git checkout } 

найти предыдущий фиксатор

 function p() { git checkout HEAD^1 } 

Мне удалось найти следующего ребенка следующим образом:

 git log --reverse --children -n1 HEAD (where 'n' is the number of children to show) 

Если ребенок совершает все на какой-либо ветви, вы можете использовать gitk --all commit^.. , где «commit» – это что-то, что идентифицирует commit. Например, если сокращенный SHA-1 фиксации является c6661c5, введите gitk --all c6661c5^..

Вероятно, вам нужно будет ввести полный SHA-1 в ячейку «SHA1 ID:» gitk. Вам понадобится полный SHA-1, который для этого примера можно получить с помощью git rev-parse c6661c5

Кроме того, git rev-list --all --children | grep '^c6661c5883bb53d400ce160a5897610ecedbdc9d' git rev-list --all --children | grep '^c6661c5883bb53d400ce160a5897610ecedbdc9d' создаст строку, содержащую все дочерние git rev-list --all --children | grep '^c6661c5883bb53d400ce160a5897610ecedbdc9d' этого коммита, предположительно, будет ли задействована ветвь.

Каждая фиксация сохраняет указатель на родителя (родители, в случае слияния (стандартного) фиксации).

Таким образом, нет способа указать на дочернее соглашение (если оно есть) от родителя.

Этот пост ( http://www.jayway.com/2015/03/30/using-git-commits-to-drive-a-live-coding-session/#comment-282667 ) показывает аккуратный способ, если это сделать, если вы можете создать хорошо определенный тег в конце стека фиксации. По существу git config --global alias.next '!git checkout `git rev-list HEAD..demo-end | tail -1`' git config --global alias.next '!git checkout `git rev-list HEAD..demo-end | tail -1`' где «demo-end» – последний тег.

Существующие ответы предполагают, что у вас есть ветка (или ссылка), содержащая обязательство, которое вы ищете.

В моем случае коммит, который я искал, не был в git rev-list --all , так как ни одна ветвь не содержала этого. В итоге я просмотрел gitk --reflog вручную.

Если вы не можете найти свою фиксацию даже в reflog, попробуйте git fsck --full чтобы перечислить git fsck --full (то есть не в какой-либо ветви), или git fsck --lost-found чтобы делать ссылки и применять методы в других ответах.

Давайте будем гением компьютера.