Как найти ближайшего родителя ветки Git?

419

Допустим, у меня есть следующий локальный репозиторий с деревом коммитов:

master --> a
            \
             \
      develop c --> d
               \
                \
         feature f --> g --> h

masterэто мое это последний код стабильного релиза , developэто мое это «следующий» код релиза , и featureэто новая функция готовится кdevelop .

То, что я хочу делать в моем удаленном репо с использованием хуков, - featureэто отказ от толчков, если commit не fявляется прямым потомком developHEAD. т.е. фиксации дерево выглядит так, потому что функция была git rebaseна d.

master --> a
            \
             \
      develop c --> d
                     \
                      \
               feature f --> g --> h

Так возможно ли:

  • Определить родительскую ветвь feature?
  • Определите коммит в родительской ветви, которая fявляется потомком?

Оттуда я бы проверил, что такое HEAD родительской ветви, и посмотрел, соответствует ли fпредшественник родительской ветви HEAD, чтобы определить, нужно ли перебазировать эту функцию.

Питер Фармер
источник
этот вопрос следует перефразировать, чтобы найти родителя родителя.
Тим Боланд

Ответы:

348

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

История Git основана на DAG коммитов. Ветви (и вообще «ссылки») - это просто временные метки, которые указывают на конкретные коммиты в постоянно растущей DAG коммитов. Таким образом, отношения между ветвями могут меняться со временем, но отношения между фиксациями не изменяются.

    ---o---1                foo
            \
             2---3---o      bar
                  \
                   4
                    \
                     5---6  baz

Похоже на bazоснове (старой версии) bar? Но что если мы удалим bar?

    ---o---1                foo
            \
             2---3
                  \
                   4
                    \
                     5---6  baz

Теперь, похоже, bazосновано на foo. Но происхождение bazне изменилось, мы просто удалили метку (и получившийся висячий коммит). А что если мы добавим новый ярлык на 4?

    ---o---1                foo
            \
             2---3
                  \
                   4        quux
                    \
                     5---6  baz

Теперь, похоже, bazосновано на quux. И все же родословная не изменилась, изменились только ярлыки.

Если, однако, мы спрашиваем «является ли коммит 6потомком коммита 3?» (предполагая , что 3и 6полный SHA-1 совершают имена), то ответ будет «да», то ли barи quuxметки присутствуют или нет.

Таким образом, вы можете задать такие вопросы, как «является ли проталкиваемый коммит потомком текущего кончика ветви разработки ?», Но вы не можете с уверенностью спросить «какова родительская ветвь проталкиваемого коммита?».

Наиболее надежный вопрос, который, кажется, приближается к тому, что вы хотите:

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

  • существует хотя бы один такой коммит?
  • все ли такие коммиты с одним родителем?

Который может быть реализован как:

pushedrev=...
basename=develop
if ! baserev="$(git rev-parse --verify refs/heads/"$basename" 2>/dev/null)"; then
    echo "'$basename' is missing, call for help!"
    exit 1
fi
parents_of_children_of_base="$(
  git rev-list --pretty=tformat:%P "$pushedrev" --not "$baserev" |
  grep -F "$baserev"
)"
case ",$parents_of_children_of_base" in
    ,)     echo "must descend from tip of '$basename'"
           exit 1 ;;
    ,*\ *) echo "must not merge tip of '$basename' (rebase instead)"
           exit 1 ;;
    ,*)    exit 0 ;;
esac

Это покроет то, что вы хотите ограничить, но, возможно, не все.

Для справки, вот расширенный пример истории:

    A                                   master
     \
      \                    o-----J
       \                  /       \
        \                | o---K---L
         \               |/
          C--------------D              develop
           \             |\
            F---G---H    | F'--G'--H'
                    |    |\
                    |    | o---o---o---N
                     \   \      \       \
                      \   \      o---o---P
                       \   \   
                        R---S

Приведенный выше код может быть использован для отклонения Hи Sпри приеме H', J, Kили N, но он также будет принимать Lи P(они включают слияние, но они не сливаются кончиком разработки ).

Чтобы также отклонить Lи P, вы можете изменить вопрос и спросить

Для всех предков push-коммитов (исключая текущий наконечник Develop и его предков):

  • есть ли коммиты с двумя родителями?
  • если нет, имеет ли хотя бы один такой коммит текущий совет развития своего (единственного) родителя?
pushedrev=...
basename=develop
if ! baserev="$(git rev-parse --verify refs/heads/"$basename" 2>/dev/null)"; then
    echo "'$basename' is missing, call for help!"
    exit 1
fi
parents_of_commits_beyond_base="$(
  git rev-list --pretty=tformat:%P "$pushedrev" --not "$baserev" |
  grep -v '^commit '
)"
case "$parents_of_commits_beyond_base" in
    *\ *)          echo "must not push merge commits (rebase instead)"
                   exit 1 ;;
    *"$baserev"*)  exit 0 ;;
    *)             echo "must descend from tip of '$basename'"
                   exit 1 ;;
esac
Крис Джонсен
источник
Я получаю это: git: fatal: неоднозначный аргумент '...': ревизия и имя файла. каково намерение тройных точек?
Джек Уклея
1
@Schneider Я почти уверен, что в этом примере символ «...» должен быть заполнителем: если вы замените его на SHA коммита, с которым вы пытаетесь выполнить эту проверку (скажем, HEAD ветви ты в данный момент включен), все работает просто отлично.
Дэниел Брэди,
Спасибо за этот сложный ответ! Это супер полезно. Я хочу сделать похожий хук, но я не хочу жестко кодировать название ветки разработки. Это означает, что я хочу ловушку для предотвращения перебазирования в ветку, отличную от родительской. Если я хорошо понимаю ваш ответ (я новичок в bash и прочее), это не отражено в вашем ответе, верно? Есть ли способ сделать это?
Кемея
Готовы ли вы ответить на связанный вопрос? Я не смог заставить ваш код работать в удаленном хранилище. Вот ссылка на следующий вопрос о том, как адаптировать ваш подход для работы с REMOTE-репозиторием: stackoverflow.com/questions/49619492/…
CodeMed
Это не сработало для меня, когда у меня было develop > release > feature, я вернулась бы к развитию, и это требует знания родителей. Решение моей проблемы было stackoverflow.com/a/56673640/2366390
verdverm
241

Перефразирование

Другой способ сформулировать вопрос: «Какой ближайший коммит находится в ветке, отличной от текущей, и какая это ветка?»

Решение

Вы можете найти это с небольшим количеством волшебства командной строки

git show-branch \
| sed "s/].*//" \
| grep "\*" \
| grep -v "$(git rev-parse --abbrev-ref HEAD)" \
| head -n1 \
| sed "s/^.*\[//" 

С awk :

git show-branch -a \
| grep '\*' \
| grep -v `git rev-parse --abbrev-ref HEAD` \
| head -n1 \
| sed 's/[^\[]*//' \
| awk 'match($0, /\[[a-zA-Z0-9\/-]+\]/) { print substr( $0, RSTART+1, RLENGTH-2 )}'

Вот как это работает:

  1. Отображение текстовой истории всех коммитов, включая удаленные ветви.
  2. Предки текущего коммита отмечены звездочкой. Отфильтруйте все остальное.
  3. Игнорировать все коммиты в текущей ветке.
  4. Первым результатом будет ближайшая ветвь предка. Игнорировать другие результаты.
  5. Названия веток отображаются [в скобках]. Игнорировать все, что находится за скобками и за скобками.
  6. Иногда имя ветки будет содержать ~ # или ^ #, чтобы указать, сколько коммитов находится между ссылочным коммитом и подсказкой ветки. Нам все равно. Игнорируй их.

И результат

Запуск вышеуказанного кода на

 A---B---D <-master
      \
       \
        C---E---I <-develop
             \
              \
               F---G---H <-topic

Даст вам, developесли вы запустите его от H и masterесли вы запустите его от I.

Код доступен как суть

Джо Крайслер
источник
24
Удален трейлинг, который вызывал ошибку. Когда я запускаю эту команду, я получаю большое количество предупреждений, жалуюсь на каждую ветвь, говорящуюcannot handle more than 25 refs
Джон Л.
1
@JoeChrysler Как вы думаете, вы можете сделать это одной строкой вместо 2, и, возможно, заставить ее работать на Mac, как ackэто не доступно на Mac (кто-то предложил заменить ackна grep)
неполярность
53
Извините, это неправильно. Вот правильный, который работал для меня:git show-branch | grep '*' | grep -v "$(git rev-parse --abbrev-ref HEAD)" | head -n1 | sed 's/.*\[\(.*\)\].*/\1/' | sed 's/[\^~].*//'
droidbot
15
@droidbot Хорошо, но нужно переупорядочить конвейеры, чтобы избежать удаления ссылок, когда grep -v catch коммит-сообщение или ваше имя ветви является частью другого имени ветви. git show-branch | sed "s/].*//" | grep "\*" | grep -v "$(git rev-parse --abbrev-ref HEAD)" | head -n1 | sed "s/^.*\[//"
Гал
3
@OlegAbrazhaev Не знаю, получил ли ты ответ на свой вопрос. используя псевдоним git: parent = "!git show-branch | grep '*' | grep -v \"$(git rev-parse --abbrev-ref HEAD)\" | head -n1 | sed 's/.*\\[\\(.*\\)\\].*/\\1/' | sed 's/[\\^~].*//' #"работает для меня
mduttondev
111

Вы также можете попробовать:

git log --graph --decorate
rcde0
источник
5
git log --graph --decorate --simplify-by-decorationгде --graphне обязательно.
Na13-c
1
git log --graph --decorate --simplify-by-decoration --oneline
anishtain4
106

мерзавец родитель

Вы можете просто запустить команду

git parent

чтобы найти родителя ветви, если вы добавите ответ @Joe Chrysler в качестве псевдонима git . Это упростит использование.

Откройте файл gitconfig, расположенный в "~/.gitconfig"любом текстовом редакторе. (Для Linux). А для Windows путь ".gitconfig" обычно находится по адресуc:\users\your-user\.gitconfig

vim  ~/.gitconfig

Добавьте следующую команду псевдонимов в файл:

[alias]
            parent = "!git show-branch | grep '*' | grep -v \"$(git rev-parse --abbrev-ref HEAD)\" | head -n1 | sed 's/.*\\[\\(.*\\)\\].*/\\1/' | sed 's/[\\^~].*//' #"

Сохраните и выйдите из редактора.

Запустите команду git parent

Это оно!

НИХИЛ СМ
источник
5
Это отличное решение. Было бы также полезно добавить некоторые примеры выходных данных, чтобы быть уверенными в ожидаемых результатах. Когда я запустил его, я получил несколько предупреждений перед самой последней строкой, которая, как мне кажется, была названием родительской ветви.
18:09
4
Работает как шарм! Для пользователей Windows На .gitconfig обычно находится в C: \ Users \ Ваш-пользователя \ .gitconfig
Zion
12
Получение cannot handle more than 25 refsисключения.
Shajin
кто-то может отредактировать это, чтобы обработать предупреждение? @ttemple, ты можешь?
NIKHIL CM
@NIKHILCM работает как Чемпион. Но у меня есть вопрос здесь, указывает ли родитель, откуда была создана ветка, или что-то еще?
Харипрасат
52

У меня есть решение вашей общей проблемы (определите, featureпроисходит ли оно от кончика develop), но оно не работает с использованием описанного вами метода.

Вы можете использовать, git branch --containsчтобы перечислить все ветви, произошедшие от кончика develop, а затем использовать, grepчтобы убедиться, что featureсреди них есть.

git branch --contains develop | grep "^ *feature$"

Если он находится среди них, он выводит " feature"на стандартный вывод и имеет код возврата 0. В противном случае он ничего не печатает и имеет код возврата 1.

Даниэль Штутцбах
источник
1
Это работает, но следует отметить, что это может занять много времени в репозитории, в котором много ссылок. Это делает его немного менее идеальным для работы, например, с крюком предварительного приема.
Ebneter
Я искал ветку, мы ее назовем <branch>, где я выполнил: git checkout -b <branch-2>от ... ЭТО ответ! Нет необходимости в grep, правда. git branch --contains <branch>
Poopy McFartnoise
44

Это работает хорошо для меня.

git show-branch | grep '*' | grep -v "$(git rev-parse --abbrev-ref HEAD)" | head -n1 | sed 's/.*\[\(.*\)\].*/\1/' | sed 's/[\^~].*//'

Вежливые ответы от: @droidbot и @Jistanidiot

Мурали Мопуру
источник
Да, но иногда это дает тебе "сломанную трубу" от grep.
Владислав Раструсный
1
*не является подходящим регулярным выражением для перехода к grep. Следует использовать grep -F '*'или grep '\*'вместо. Хорошее решение в противном случае.
Ариэльф
У меня нет выхода.
Сандип Субеди
у меня работает ....
roottraveller
11

Поскольку ни один из ответов выше не работал в нашем хранилище, я хочу поделиться своим собственным способом, используя последние слияния в git log:

#!/bin/bash
git log --oneline --merges "$@" | grep into | sed 's/.* into //g' | uniq --count | head -n 10

Поместите его в скрипт с именем git-last-merges, который также принимает имя ветви в качестве аргумента (вместо текущей ветви), а также другие git logаргументы

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

РЕДАКТИРОВАТЬ: Если вы git rebaseчасто используете дочерние ветви (и слияния часто переадресовываются, так что не слишком много коммитов слияния), этот ответ не будет работать хорошо, поэтому я написал скрипт для подсчета коммитов вперед (обычный и слияния) и за коммитами (не должно быть никаких слияний в родительской ветке) во всех ветках по сравнению с текущей веткой. Просто запустите этот скрипт и дайте мне знать, работает у вас или нет

#!/bin/bash
HEAD="`git rev-parse --abbrev-ref HEAD`"
echo "Comparing to $HEAD"
printf "%12s  %12s   %10s     %s\n" "Behind" "BehindMerge" "Ahead" "Branch"
git branch | grep -v '^*' | sed 's/^\* //g' | while read branch ; do
    ahead_merge_count=`git log --oneline --merges $branch ^$HEAD | wc -l`
    if [[ $ahead_merge_count != 0 ]] ; then
        continue
    fi
    ahead_count=`git log --oneline --no-merges $branch ^$HEAD | wc -l`
    behind_count=`git log --oneline --no-merges ^$branch $HEAD | wc -l`
    behind_merge_count=`git log --oneline --merges ^$branch $HEAD | wc -l`
    behind="-$behind_count"
    behind_merge="-M$behind_merge_count"
    ahead="+$ahead_count"
    printf "%12s  %12s   %10s     %s\n" "$behind" "$behind_merge" "$ahead" "$branch"
done | sort -n
saeedgnu
источник
Спасибо. Хотя это может работать не очень хорошо, если вы rebaseчасто используете (и слияния fast-forwardредактируются часто). Я отредактирую свой ответ, если найду лучшее решение.
saeedgnu
1
Единственный? пока ответьте, что работало разумно для меня в случае, когда текущая ветка является master. Большинство других решений дали случайный (и явно некорректный) результат в этом, по общему признанию, краевом случае, когда нет фактических родительских ветвей.
Ариэльф
Это единственный ответ, который работал для меня. Чтобы получить первого родителя вместо списка первых 10, вы можете использовать это: git log --oneline --merges "$@" | grep into | sed 's/.* into //g' | uniq --count | head -n 1 | cut -d ' ' -f 8
lots0logs
10

Решение

Решение, основанное на,git show-branch мне не совсем помогло (см. Ниже), поэтому я объединил его с решением, основанным наgit log и в конечном итоге с этим:

git log --decorate --simplify-by-decoration --oneline \ # selects only commits with a branch or tag
      | grep -v "(HEAD" \                               # removes current head (and branch)
      | head -n1 \                                      # selects only the closest decoration
      | sed 's/.* (\(.*\)) .*/\1/' \                    # filters out everything but decorations
      | sed 's/\(.*\), .*/\1/' \                        # picks only the first decoration
      | sed 's/origin\///'                              # strips "origin/" from the decoration

Ограничения и предостережения

  • HEAD может быть отсоединен (многие инструменты CI делают это для обеспечения правильной фиксации в заданной ветви), но исходная ветвь и локальная ветвь должны быть как на уровне, так и "выше" текущего HEAD.
  • Должно быть никаких тегов (я полагаю; я не проверял скрипт на коммитах с тегом между дочерней и родительской ветвями)
  • сценарий опирается на тот факт, что «ГОЛОВА» всегда указывается в качестве первого украшения по logкоманде
  • работает скрипт на masterиdevelop результаты ( в основном) в<SHA> Initial commit

Результаты

 A---B---D---E---F <-origin/master, master
      \      \
       \      \
        \      G---H---I <- origin/hotfix, hotfix
         \
          \
           J---K---L <-origin/develop, develop
                \
                 \
                  M---N---O <-origin/feature/a, feature/a
                       \   \
                        \   \
                         \   P---Q---R <-origin/feature/b, feature/b
                          \
                           \
                            S---T---U <-origin/feature/c, feature/c

Несмотря на существование локальной ветви (например, origin/topicприсутствует только с момента фиксацииO была извлечена непосредственно его SHA), скрипт должен напечатать следующее:

  • Для фиксаций G, H,I (филиал hotfix) →master
  • Для фиксаций M, N,O (филиал feature/a) →develop
  • Для фиксаций S, T,U (филиал feature/c) →develop
  • Для фиксаций P, Q,R (филиал feature/b) →feature/a
  • Для фиксаций J, K, L(филиалdevelop ) → <sha> Initial commit*
  • Для коммитов B,D , E, F(филиал master) →<sha> Initial commit

* - или master если developкоммиты были на вершине HEAD мастера (~ мастер мог бы быстро развиваться)


Почему у меня не работает шоу-ветка

Решение на основеgit show-branch оказалось ненадежным для меня в следующих ситуациях:

  • ОТДЕЛЬНАЯ ГОЛОВА - включая случай с отсоединенной головкой означает замену grep '\*' \на `grep '!' \ - и это только начало всех неприятностей
  • работает скрипт на masterиdevelop приводит developи `` соответственно
  • ветви наmaster ветви ( hotfix/ветви) заканчиваются developкак родитель, так как их ближайший masterродительский филиал был отмечен !вместо *по причине.
Мэтт Стувисант
источник
2
Единственный ответ, который работал - как псевдоним Git:"!git log --decorate --simplify-by-decoration --oneline | grep -v '(HEAD' | head -n1 | sed 's/.* (\\(.*\\)) .*/\\1/' | sed 's/\\(.*\\), .*/\\1/' | sed 's/origin\\///'"
Ян Кемп
8

Помните, что, как описано в «Git: Поиск ветви, из которой получен коммит» , вы не можете легко определить ветку, в которой был сделан этот коммит (ветви могут быть переименованы, перемещены, удалены ...), даже если git branch --contains <commit>это начало.

  • Вы можете вернуться от коммита к коммиту, пока git branch --contains <commit>не перечислите featureветку и списокdevelop ветвей,
  • сравните этот коммит SHA1 с /refs/heads/develop

Если идентификаторы двух коммитов совпадают, вы можете идти (это будет означать, что featureветвь имеет свое происхождение в HEAD of develop).

VonC
источник
6

Магия командной строки JoeChrysler может быть упрощена. Вот логика Джо - для краткости я ввел параметр, названный cur_branchвместо подстановки команд `git rev-parse --abbrev-ref HEAD`в обеих версиях; это можно инициализировать так:

cur_branch=$(git rev-parse --abbrev-ref HEAD)

Тогда вот трубка Джо:

git show-branch -a           |
  grep '\*'                  | # we want only lines that contain an asterisk
  grep -v "$cur_branch"      | # but also don't contain the current branch
  head -n1                   | # and only the first such line
  sed 's/.*\[\(.*\)\].*/\1/' | # really, just the part of the line between []
  sed 's/[\^~].*//'            # and with any relative refs (^, ~n) removed

Мы можем выполнить то же самое, что и все пять из этих отдельных фильтров команд, в относительно простой awkкоманде:

git show-branch -a |
  awk -F'[]^~[]' '/\*/ && !/'"$cur_branch"'/ {print $2;exit}'  

Это ломается так:

-F'[]^~[]' 

разделить строку на поля в ], ^, ~и [персонажах.

/\*/                      

Найти строки, которые содержат звездочку

&& !/'"$cur_branch"'/

... но не текущее имя ветки

{ print $2;               

Когда вы найдете такую ​​строку, напечатайте ее второе поле (то есть часть между первым и вторым вхождением наших символов разделителя полей). Для простых имен ветвей это будет именно то, что находится в скобках; для ссылок с относительными переходами это будет просто имя без модификатора. Таким образом, наш набор разделителей полей обрабатывает назначение обеих sedкоманд.

  exit }

Тогда выходите немедленно. Это означает, что он обрабатывает только первую совпадающую строку, поэтому нам не нужно передавать данные через него head -n 1.

Марк Рид
источник
3
Обратите внимание, что некоторые ветви могут отсутствовать в выводе из-за слишком большого количества ссылок. Вместо этого они отображаются как предупреждения на stderr.
Цитракс
5

Вот реализация Power Mark для решения Марка Рида:

git show-branch -a | where-object { $_.Contains('*') -eq $true} | Where-object {$_.Contains($branchName) -ne $true } | select -first 1 | % {$_ -replace('.*\[(.*)\].*','$1')} | % { $_ -replace('[\^~].*','') }
chrisevett
источник
5

Я не говорю, что это хороший способ решить эту проблему, однако, похоже, это работает для меня.

git branch --contains $(cat .git/ORIG_HEAD) Проблема в том, что cat'ing файл заглядывает во внутреннюю работу git, так что это не обязательно совместимо вперед (или обратно).

user1529413
источник
3

Кроссплатформенная реализация с Ant

    <exec executable="git" outputproperty="currentBranch">
        <arg value="rev-parse" />  
        <arg value="--abbrev-ref" />  
        <arg value="HEAD" />  
    </exec>

    <exec executable="git" outputproperty="showBranchOutput">
        <arg value="show-branch" />  
        <arg value="-a" />  
    </exec>

    <loadresource property="baseBranch">
      <propertyresource name="showBranchOutput"/>
          <filterchain>
            <linecontains>
              <contains value="*"/>
            </linecontains>
            <linecontains negate="true">
              <contains value="${currentBranch}"/>
            </linecontains>
            <headfilter lines="1"/>
            <tokenfilter>
                <replaceregex pattern=".*\[(.*)\].*" replace="\1"/>
                <replaceregex pattern="[\^~].*" replace=""/>
            </tokenfilter>
          </filterchain>
    </loadresource>

    <echo message="${currentBranch} ${baseBranch}" />
ENargit
источник
2

@Mark Reed: Вы должны добавить, что строка коммита должна содержать не только звездочку, но и начинаться со звездочки! В противном случае сообщения о фиксации, содержащие звездочку, также включаются в соответствующие строки. Так и должно быть:

git show-branch -a | awk -F'[]^~[]' '/^\*/ && !/'"$current_branch"'/ {print $2;exit}'

или длинная версия:

git show-branch -a           |
  awk '^\*'                  | # we want only lines that contain an asterisk
  awk -v "$current_branch"   | # but also don't contain the current branch
  head -n1                   | # and only the first such line
  sed 's/.*\[\(.*\)\].*/\1/' | # really, just the part of the line between []
  sed 's/[\^~].*//'            # and with any relative refs (^, ~n) removed`
Ladiko
источник
2
vbc=$(git rev-parse --abbrev-ref HEAD)
vbc_col=$(( $(git show-branch | grep '^[^\[]*\*' | head -1 | cut -d* -f1 | wc -c) - 1 )) 
swimming_lane_start_row=$(( $(git show-branch | grep -n "^[\-]*$" | cut -d: -f1) + 1 )) 
git show-branch | tail -n +$swimming_lane_start_row | grep -v "^[^\[]*\[$vbc" | grep "^.\{$vbc_col\}[^ ]" | head -n1 | sed 's/.*\[\(.*\)\].*/\1/' | sed 's/[\^~].*//'

Достигает того же конца, что и ответ Марка Рида, но использует гораздо более безопасный подход, который не ведет себя неправильно в ряде сценариев:

  1. Последний коммит родительской ветви - это слияние, поэтому столбец - не*
  2. Сообщение коммита содержит имя ветви
  3. Сообщение коммита содержит *
Хаоян Фэн
источник
0

Любой, кто хочет сделать это в наши дни - приложение Atlassian SourceTree показывает вам наглядное представление о том, как ваши ветви связаны друг с другом, то есть, где они начались и где они в настоящее время находятся в порядке фиксации (например, HEAD или 4 коммитов и т. Д.) ,

Джейк
источник
0

Если вы используете Source Tree, посмотрите на детали вашего коммита> Parents>, тогда вы увидите подчеркнутые номера коммитов (ссылки)

Mike6679
источник
0

Альтернатива: git rev-list master | grep "$(git rev-list HEAD)" | head -1

Получите последний коммит, который является моей веткой и master(или любой веткой, которую вы хотите указать)

Александр Вудс
источник
0

Это не сработало для меня, когда я сделал что-то подобное develop > release-v1.0.0 > feature-foo, все пошло бы назад, чтобы развиться, заметьте, что произошел ребазинг, не уверен, что это усугубляет мою проблему ...

Следующий код дал мне правильный коммит

git log --decorate \
  | grep 'commit' \
  | grep 'origin/' \
  | head -n 2 \
  | tail -n 1 \
  | awk '{ print $2 }' \
  | tr -d "\n"
verdverm
источник