Есть ли какой-нибудь способ узнать, из какой ветки происходит фиксация с учетом ее sha1?
Бонусные баллы, если вы можете сказать мне, как это сделать, используя Ruby Grit.
Есть ли какой-нибудь способ узнать, из какой ветки происходит фиксация с учетом ее sha1?
Бонусные баллы, если вы можете сказать мне, как это сделать, используя Ruby Grit.
Хотя Дав верно, что информация напрямую не хранится, это не значит, что вы никогда не узнаете. Вот несколько вещей, которые вы можете сделать.
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 ответить на связанный вопрос помогает в этой теме.
Эта простая команда работает как шарм:
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
Обновление в декабре 2013 года:
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
[...]
Эта программа не учитывает эффекты выбора вишни коммитов, только операции слияния.
Например, чтобы найти, что 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
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)
Недопустимый вариант - использовать инструмент tig
1 on HEAD
, найти зафиксировать, а затем визуально следовать за строкой от этой фиксации до тех пор, пока не увидит фиксацию слияния. Сообщение слияния по умолчанию должно указывать, какая ветка объединяется, где:)
1 Tig - это интерфейс текстового режима на основе ncurses для git. Он функционирует главным образом в качестве браузера хранилища Git, но также может помочь в организации изменения для фиксации на уровне блоков и выступать в качестве пейджера для вывода из различные команды Git.
В качестве эксперимента я сделал крюк post-commit, который хранит информацию о текущей проверенной ветке в метаданных фиксации. Я также немного модифицировал gitk, чтобы показать эту информацию.
Вы можете проверить это здесь: https://github.com/pajp/branch-info-commits
Я имею дело с той же проблемой (многоотраслевой конвейер 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'
Если ОП пытается определить историю 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: сохранение заголовка
Код>
Используйте нижеприведенное, если вам небезразлично состояние выхода из оболочки:
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
0
.% git branch-name 4bc6188
Multiple branches:
attempt-extract
master%
% echo $?
1
1
.Из-за статуса выхода их можно безопасно строить. Например, чтобы использовать пульт для извлечения:
remote-fetch = !"branch=$(git branch-name \"$1\") && git config branch.\"$branch\".remote || echo origin #"
Я думаю, что кто-то должен столкнуться с той же проблемой, что не может найти ветку, хотя на самом деле она существует в одной ветке.
Тебе лучше сначала потянуть все:
git pull --all
Затем выполните поиск по ветки:
git name-rev <SHA>
или:
git branch --contains <SHA>
@khichar.anil рассказал обо всем этом в своем ответе.
Просто добавление флага для удаления тегов дает нам:
git name-rev --name-only --exclude=tags/* $SHA
Чтобы найти локальную ветвь
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'
Помимо поиска по всему дереву, пока не найдете соответствующий хеш, нет.