Поиск ветки git commit - PullRequest
       90

Поиск ветки git commit

543 голосов
/ 25 апреля 2010

Есть ли способ узнать, из какой ветви происходит коммит с учетом его ша1?

Бонусные баллы, если вы можете сказать мне, как сделать это, используя Ruby Grit.

Ответы [ 12 ]

763 голосов
/ 25 апреля 2010

Несмотря на то, что Дэв прав, информация не хранится напрямую, это не значит, что вы никогда не узнаете. Вот несколько вещей, которые вы можете сделать.

Поиск ветвей, на которых зафиксирован коммит

git branch --contains <commit>

Это расскажет вам все ветви, которые имеют данный коммит в своей истории. Очевидно, что это менее полезно, если коммит уже был объединен.

Поиск по журналам

Если вы работаете в репозитории, в котором была сделана фиксация, вы можете найти в журналах регистрации строку для этой фиксации. Рефлоги старше 90 дней удаляются git-gc, поэтому если коммит слишком старый, вы его не найдете. Тем не менее, вы можете сделать это:

git reflog show --all | grep a871742

найти коммит a871742. Вывод должен быть примерно таким:

a871742 refs/heads/completion@{0}: commit (amend): mpc-completion: total rewrite

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

git reflog show на самом деле просто псевдоним для git log -g --abbrev-commit --pretty=oneline, поэтому, если вы хотите поиграть с форматом вывода, чтобы сделать разные вещи доступными для grep, это ваша отправная точка!

Если вы не работаете в репозитории, в котором была сделана фиксация, лучшее, что вы можете сделать в этом случае, - это изучить reflogs и выяснить, когда коммит был впервые представлен в вашем репо; если повезет, вы взяли ветвь, которой он был посвящен. Это немного сложнее, потому что вы не можете одновременно обходить как дерево коммитов, так и флаги. Вы хотите проанализировать вывод reflog, изучив каждый хеш, чтобы увидеть, содержит ли он требуемый коммит или нет.

Найти последующий коммит слияния

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

git log --merges <commit>..

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

Если вы хотите рассчитывать на это, вы можете использовать опцию --no-ff для git merge, чтобы форсировать создание коммитов слияния даже в случае ускоренной перемотки вперед. (Однако не слишком рвитесь, это может стать запутанным, если его чрезмерно использовать.) Ответ VonC на связанный вопрос услужливо развивает эту тему.

71 голосов
/ 08 марта 2018

Эта простая команда работает как шарм:

git name-rev <SHA>

Например (где test-branch - имя ветви):

git name-rev 651ad3a
251ad3a remotes/origin/test-branch

Даже это работает для сложных сценариев, таких как:

origin/branchA/
              /branchB
                      /commit<SHA1>
                                   /commit<SHA2>

Здесь git name-rev commit<SHA2> возвращает BranchB

44 голосов
/ 22 сентября 2010

Обновление за декабрь 2013 года:

sschuberth комментарии

git-what-branch (скрипт Perl, см. Ниже), похоже, больше не поддерживается.
git-when-merged - это альтернатива, написанная на Python, которая очень хорошо работает для меня.

Он основан на " Найти коммит слияния, который включает определенный коммит ".

git when-merged [OPTIONS] COMMIT [BRANCH...]

Найти, когда коммит был объединен в одну или несколько ветвей.
Найдите коммит слияния, который принес COMMIT в указанные ФИЛИАЛЫ.

В частности, ищите самый старый коммит в истории первого родителя BRANCH, который содержит COMMIT в качестве предка.


Оригинальный ответ сентябрь 2010 г .:

Себастьен Душ просто дернул (за 16 минут до ответа SO):

git-what-branch : Узнайте, в какой ветке находится коммит или как он попал в именованную ветку

Это скрипт Perl из Сет Робертсон , который кажется очень интересным:

СИНТАКСИС

git-what-branch [--allref] [--all] [--topo-order | --date-order ]
[--quiet] [--reference-branch=branchname] [--reference=reference]
<commit-hash/tag>...

ОБЗОР

Сообщите нам (по умолчанию) самый ранний причинный путь коммитов и слияний, чтобы запрошенный коммит попал в именованную ветвь.
Если фиксация была сделана непосредственно в именованной ветви, это, очевидно, самый ранний путь.

Под самым ранним причинным путем мы подразумеваем путь, который слился в названную ветвь как можно раньше под временем фиксации (если не указано --topo-order).

ПРОИЗВОДИТЕЛЬНОСТЬ

Если во многих ветвях (например, сотнях) содержится фиксация, системе может потребоваться много времени (для определенного коммита в дереве linux потребовалось 8 секунд, чтобы исследовать ветку, но для отслеживания было более 200 веток-кандидатов) по пути к каждому коммиту.
Выбор конкретного --reference-branch --reference tag для проверки будет в сотни раз быстрее (если у вас есть сотни веток-кандидатов).

Примеры

 # git-what-branch --all 1f9c381fa3e0b9b9042e310c69df87eaf9b46ea4
 1f9c381fa3e0b9b9042e310c69df87eaf9b46ea4 first merged onto master using the following minimal temporal path:
   v2.6.12-rc3-450-g1f9c381 merged up at v2.6.12-rc3-590-gbfd4bda (Thu May  5 08:59:37 2005)
   v2.6.12-rc3-590-gbfd4bda merged up at v2.6.12-rc3-461-g84e48b6 (Tue May  3 18:27:24 2005)
   v2.6.12-rc3-461-g84e48b6 is on master
   v2.6.12-rc3-461-g84e48b6 is on v2.6.12-n
   [...]

Эта программа не учитывает эффекты выбора вишни коммитов интереса, только операции слияния.

27 голосов
/ 29 октября 2016

Например, чтобы найти, что c0118fa коммит произошел от redesign_interactions

* ccfd449 (HEAD -> develop) Require to return undef if no digits found
*   93dd5ff Merge pull request #4 from KES777/clean_api
|\  
| * 39d82d1 Fix tc0118faests for debugging debugger internals
| * ed67179 Move &push_frame out of core
| * 2fd84b5 Do not lose info about call point
| * 3ab09a2 Improve debugger output: Show info about emitted events
| *   a435005 Merge branch 'redesign_interactions' into clean_api
| |\  
| | * a06cc29 Code comments
| | * d5d6266 Remove copy/paste code
| | * c0118fa Allow command to choose how continue interaction
| | * 19cb534 Emit &interact event

Вы должны запустить:

git log c0118fa..HEAD --ancestry-path --merges

И прокрутите вниз, чтобы найти последний объединить коммит. Который является:

commit a435005445a6752dfe788b8d994e155b3cd9778f
Merge: 0953cac a06cc29
Author: Eugen Konkov
Date:   Sat Oct 1 00:54:18 2016 +0300

    Merge branch 'redesign_interactions' into clean_api

UPD
Или только одна команда:

git log c0118fa..HEAD --ancestry-path --merges --oneline --color | tail -n 1
8 голосов
/ 23 октября 2013

git branch --contains <ref> - наиболее очевидная «фарфоровая» команда для этого. Если вы хотите сделать что-то похожее только с помощью «сантехнических» команд:

COMMIT=$(git rev-parse <ref>) # expands hash if needed
for BRANCH in $(git for-each-ref --format "%(refname)" refs/heads); do
  if $(git rev-list $BRANCH | fgrep -q $COMMIT); then
    echo $BRANCH
  fi
done

(кросспост из этого SO ответа )

4 голосов
/ 24 сентября 2013

Бедняжка может использовать инструмент tig 1 на HEAD, искать коммит, а затем визуально следовать по линии от этого коммита до коммит слияния виден. В сообщении о слиянии по умолчанию должно быть указано, в какую ветвь происходит слияние:)

1 Tig - это основанный на ncurses интерфейс текстового режима для git. Это функционирует главным образом как браузер Git-репозитория, но может также помочь в организации изменения для фиксации на уровне чанка и действуют как пейджер для вывода из различные команды Git.

3 голосов
/ 14 февраля 2012

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

Вы можете проверить это здесь: https://github.com/pajp/branch-info-commits

2 голосов
/ 23 октября 2018

Я имею дело с той же проблемой (многоотраслевой конвейер jenkins) - иметь только информацию о коммите и пытаться найти имя ветки, откуда изначально произошел этот коммит. Он должен работать для удаленных филиалов, локальные копии не доступны.

Вот с чем я работаю:

git rev-parse HEAD | xargs git name-rev

При желании вы можете обрезать вывод:

git rev-parse HEAD | xargs git name-rev | cut -d' ' -f2 | sed 's/remotes\/origin\///g'
0 голосов
/ 20 октября 2018

TL; DR:

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

  • branch-current - название текущей ветви
  • branch-names - чистые имена веток (по одному в строке)
  • branch-name - Убедитесь, что из branch-names

И branch-name, и branch-names принимают коммит в качестве аргумента и по умолчанию HEAD, если ничего не дано.


Псевдонимы, полезные в сценариях

branch-current = "symbolic-ref --short HEAD"  # https://stackoverflow.com/a/19585361/5353461
branch-names = !"[ -z \"$1\" ] && git branch-current 2>/dev/null || git branch --format='%(refname:short)' --contains \"${1:-HEAD}\" #"  # https://stackoverflow.com/a/19585361/5353461
branch-name = !"br=$(git branch-names \"$1\") && case \"$br\" in *$'\\n'*) printf \"Multiple branches:\\n%s\" \"$br\">&2; exit 1;; esac; echo \"$br\" #"

Фиксация возможна только из одной ветви

% git branch-name eae13ea
master
% echo $?
0
  • Выход на STDOUT
  • Выходное значение 0.

Коммит достижим из нескольких ветвей

% git branch-name 4bc6188
Multiple branches:
attempt-extract
master%                                                                                                                                                                                                            
% echo $?
1
  • Выход на STDERR
  • Выходное значение 1.

Из-за статуса выхода их можно безопасно строить. Например, чтобы получить пульт дистанционного управления для извлечения:

remote-fetch = !"branch=$(git branch-name \"$1\") && git config branch.\"$branch\".remote || echo origin #"
0 голосов
/ 27 января 2018

Если OP пытается определить историю , которая была пройдена ветвью при создании определенного коммита («выяснить, из какой ветки происходит коммит, учитывая его sha1»), то без рефлога нет записей в базе данных объектов git , которая показывает, какая именованная ветвь была связана с какой историей фиксации.

(я отправил это как ответ на комментарий)

Надеюсь, этот сценарий иллюстрирует мою точку зрения:

rm -rf /tmp/r1 /tmp/r2; mkdir /tmp/r1; cd /tmp/r1
git init; git config user.name n; git config user.email e@x.io
git commit -m"empty" --allow-empty; git branch -m b1; git branch b2
git checkout b1; touch f1; git add f1; git commit -m"Add f1"
git checkout b2; touch f2; git add f2; git commit -m"Add f2"
git merge -m"merge branches" b1; git checkout b1; git merge b2
git clone /tmp/r1 /tmp/r2; cd /tmp/r2; git fetch origin b2:b2
set -x;
cd /tmp/r1; git log --oneline --graph --decorate; git reflog b1; git reflog b2;
cd /tmp/r2; git log --oneline --graph --decorate; git reflog b1; git reflog b2;

Выходные данные показывают отсутствие какого-либо способа узнать, поступил ли коммит с 'Add f1' из ветви b1 или b2 из удаленного клона / tmp / r2

(последние строки вывода здесь)

+ cd /tmp/r1
+ git log --oneline --graph --decorate
*   f0c707d (HEAD, b2, b1) merge branches
|\  
| * 086c9ce Add f1
* | 80c10e5 Add f2
|/  
* 18feb84 empty
+ git reflog b1
f0c707d b1@{0}: merge b2: Fast-forward
086c9ce b1@{1}: commit: Add f1
18feb84 b1@{2}: Branch: renamed refs/heads/master to refs/heads/b1
18feb84 b1@{3}: commit (initial): empty
+ git reflog b2
f0c707d b2@{0}: merge b1: Merge made by the 'recursive' strategy.
80c10e5 b2@{1}: commit: Add f2
18feb84 b2@{2}: branch: Created from b1
+ cd /tmp/r2
+ git log --oneline --graph --decorate
*   f0c707d (HEAD, origin/b2, origin/b1, origin/HEAD, b2, b1) merge branches
|\  
| * 086c9ce Add f1
* | 80c10e5 Add f2
|/  
* 18feb84 empty
+ git reflog b1
f0c707d b1@{0}: clone: from /tmp/r1
+ git reflog b2
f0c707d b2@{0}: fetch origin b2:b2: storing head
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...