Поиск какой ветки 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
Помимо поиска по всему дереву, пока не найдете соответствующий хеш, нет.