Я предполагаю, что HEAD - это наиболее общий c способ ссылки на текущую ветку ...
Да, это так. Хотя здесь есть ловушка, как мы увидим через мгновение.
, но мне также нужен универсальный c способ ссылки на пульт по умолчанию для текущей ветви?
Есть много способов сделать это, и у каждого есть свои возможные ловушки, но я думаю, что самое простое - использовать git config
, чтобы прочитать обратно половину текущей настройки upstream текущей ветви.
Очевидным подводным камнем здесь является то, что текущая ветвь не может иметь восходящий поток.
Если у вас современный Git, git rev-parse
может вернуть информацию о восходящем потоке любой ветви, включая текущую ветвь:
$ git rev-parse --symbolic-full-name HEAD
refs/heads/master
$ git rev-parse --symbolic-full-name HEAD@{u}
refs/remotes/origin/master
Здесь текущая ветвь равна master
, а ее восходящая ветвь равна origin/master
. Они используют полное написание каждого ссылки, что является хорошей идеей, если вы пишете сценарии, поскольку сокращенные имена (master
и origin/master
) могут неправильно анализироваться: например, master
может превратиться в refs/tags/master
, если кто-то создал тег с именем master
.
Восходящий поток, если таковой имеется - git branch --unset-upstream master
будет удалять восходящий поток, например, для master
- устанавливается как две части:
$ git config --get branch.master.remote
origin
$ git config --get branch.master.merge
refs/heads/master
Параметр branch.master.remote
- это именно то, что вам нужно: имя пульта или, в данном случае, origin
. Поэтому, если вы впервые найдете текущее имя ветви :
$ git symbolic-ref --short HEAD
master
, вы можете использовать его для получения соответствующего удаленного имени:
branch=$(git symbolic-ref --short HEAD) || die ...
remote=$(git config --get branch.$branch.remote) || die ...
Теперь вы можете запустить:
$ git fetch $remote HEAD
Но теперь мы попали в первую ловушку, которую я упомянул:
remote: Enumerating objects: 928, done.
remote: Counting objects: 100% (928/928), done.
remote: Compressing objects: 100% (401/401), done.
remote: Total 928 (delta 601), reused 809 (delta 526)
Receiving objects: 100% (928/928), 843.84 KiB | 1.62 MiB/s, done.
Resolving deltas: 100% (601/601), completed with 74 local objects.
From [url]
* branch HEAD -> FETCH_HEAD
Обратите внимание, что, хотя у меня есть современный (я sh) Git здесь (2.24.0 ), Я не получил обновленный origin/master
. Чтобы сделать это, я должен использовать вместо этого:
$ git fetch $remote $branch
From [url]
* branch master -> FETCH_HEAD
c7a6207591..51ebf55b93 master -> origin/master
На этот раз мой origin/master
был обновлен соответствующим образом.
Редактировать: Я не упомянул об этом изначально, но мы можем видеть здесь, что мои Git попросили их Git для их HEAD
. Их HEAD
это их master
; будь я в какой-то другой ветке, я бы все равно получил их HEAD
, то есть их master
, в моем .git/FETCH_HEAD
. Так что это не просто косметика c: вы должны указать здесь свое Git название ветви, а не символ c имя HEAD
. Сравните с git push
, где вы можете безопасно использовать HEAD
для вашей стороны, потому что с git push
ваш Git, а не их, разрешает символ c имя HEAD
на имя ветви.
Заключение и еще один подводный камень
Сначала вы должны получить текущее имя ветви. Помните, что это может не сработать: может не быть текущего имени ветви. Затем используйте git config --get
, чтобы получить remote часть восходящей настройки. (Оставшаяся часть требует сопоставления с помощью сопоставления по умолчанию для удаленного извлечения refspe c, но нам это не нужно - git fetch
справится с этим - так что вообще не беспокойтесь о наборе branch.$branch.merge
.)
Последняя ошибка, о которой стоит упомянуть, это: в приведенном выше примере кода используется git config --get ... || die ...
, где die
- это (предположительно) функция оболочки для полного выхода из сценария. Однако, если у нет установлен восходящий поток для текущей ветви, git fetch
сама не будет выходить из этой точки. Он будет просто использовать жестко закодированное имя origin
. Таким образом, в зависимости от того, насколько рабски вы хотите имитировать raw git fetch
, вы можете захотеть:
remote=$(git config --get branch.$branch.remote) || remote=origin
. Поскольку вы пишете сценарий, вы можете контролировать край и ошибки здесь.