Поиск какой ветки a git произошел из

Есть ли какой-нибудь способ узнать, из какой ветки происходит фиксация с учетом ее sha1?

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

Ответы

Ответ 1

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

Найти ветки фиксации на

git branch --contains <commit>

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

Искать в журналах

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

git reflog show --all | grep a871742

найти commit a871742. Результат должен быть примерно таким:

a871742 refs/heads/[email protected]{0}: commit (amend): mpc-completion: total rewrite

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

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

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

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

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

git log --merges <commit>..

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

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

Ответ 2

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

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

Ответ 3

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

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

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

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

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

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

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


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

Себастьен душ только что подкрутил (за 16 минут до ответа ТАК):

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

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

SYNOPSIS

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

OVERVIEW

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

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

PERFORMANCE

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

EXAMPLES

 # 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
   [...]

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

Ответ 4

Например, чтобы найти, что c0118fa совершил 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

Ответ 5

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

(crosspost from этот ответ SO)

Ответ 6

Недопустимый вариант - использовать инструмент tig 1 on HEAD, найти зафиксировать, а затем визуально следовать за строкой от этой фиксации до тех пор, пока не увидит фиксацию слияния. Сообщение слияния по умолчанию должно указывать, какая ветка объединяется, где:)

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

Ответ 7

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

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

Ответ 8

Я имею дело с той же проблемой (многоотраслевой конвейер 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'

Ответ 9

Если ОП пытается определить историю history, которая была пройдена веткой, когда была создана конкретная фиксация ( "узнать, какая ветвь совершает происходит из-за ее sha1" ), то без reflog там нет записей в базе данных объектов git, которая показывает, какая именованная ветвь была связана с историей фиксации.

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

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

  rm -rf/tmp/r1/tmp/r2; mkdir/tmp/r1; cd/tmp/r1
git init; git config user.name n; git config user.email [email protected]
git commit -m "empty" --allow-empty; git branch -m b1; ветвь git b2
git checkout b1; touch f1; git add f1; git commit -m "Добавить f1" 
git checkout b2; touch f2; git add f2; git commit -m "Добавить f2" 
git merge -m "слияние ветвей" 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/r 2

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

  + cd/tmp/r1
+ git log --online --graph - decorate
* f0c707d (HEAD, b2, b1) объединяет ветки
| \
| * 086c9ce Добавить f1
* | 80c10e5 Добавить f2
|/
* 18feb84 пусто
+ git reflog b1
f0c707d b1 @{0}: слияние b2: перемотка вперед
086c9ce b1 @{1}: commit: Добавить f1
18feb84 b1 @{2}: Филиал: переименован refs/heads/master в refs/heads/b1
18feb84 b1 @{3}: commit (начальный): пустой
+ git reflog b2
f0c707d b2 @{0}: merge b1: Слияние производится по стратегии "рекурсивный".
80c10e5 b2 @{1}: commit: Добавить f2
18feb84 b2 @{2}: branch: Создано из b1
+ cd/tmp/r2
+ git log --online --graph - decorate
* f0c707d (HEAD, origin/b2, origin/b1, origin/HEAD, b2, b1) объединяет ветки
| \
| * 086c9ce Добавить f1
* | 80c10e5 Добавить f2
|/
* 18feb84 пусто
+ git reflog b1
f0c707d b1 @{0}: clone: ​​from/tmp/r1
+ git reflog b2
f0c707d b2 @{0}: выборка происхождения b2: b2: сохранение заголовка
Код>

Ответ 10

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 #"

Ответ 11

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

Тебе лучше сначала потянуть все:

git pull --all

Затем выполните поиск по ветки:

git name-rev <SHA>

или:

git branch --contains <SHA>

Ответ 12

@khichar.anil рассказал обо всем этом в своем ответе.

Просто добавление флага для удаления тегов дает нам:

git name-rev --name-only --exclude=tags/* $SHA

Ответ 13

Чтобы найти локальную ветвь

grep -lR YOUR_COMMIT .git/refs/heads | sed 's/.git\/refs\/heads\///g'

Чтобы найти удаленную ветвь

grep -lR $commit .git/refs/remotes | sed 's/.git\/refs\/remotes\///g'

Ответ 14

Помимо поиска по всему дереву, пока не найдете соответствующий хеш, нет.