Почему git update-ref принимает ссылки, отличные от /refs?

в то время как команды, такие как "git log", с радостью примут разные выражения для одного и того же ref, например

refs/heads/master
heads/master
master

это неверно для "Git update-ref". Например

git update-ref master HEAD^

- это не то же самое как

git update-ref refs/heads/master HEAD^

первая команда создает новую ссылку .git / master (и, в свою очередь, вводит двусмысленность в отношении refs/heads/master). Только вторая команда действительно обновляет голову мастера. (.git / refs / heads / master)

Почему git update-ref принимает ссылки без префикса " refs/"? Разве не должно быть хотя бы предупреждения или опции командной строки для принудительного создания таких ссылок?

мне потребовалось довольно много времени, чтобы понять, почему

git update-ref master HEAD^

не работает, как ожидалось.

2 ответов


tl; dr

главная причина, почему git log и git update-ref вести себя по-другому, потому что git-log это высокого уровня command-и поэтому разработан, чтобы быть удобным для пользователя-в то время как git-update-ref - это низкий уровень команда предназначена для использования в скриптах.

керамогранит и сантехника

на языке Git команды высокого уровня называются фарфор в то время как низшие звенья называются сантехники.

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

git-update-ref

пока git-log способен разрешить ссылки, git-update-ref – это команда, сантехника – интерпретирует первый аргумент как ссылка или обычный имя файла в зависимости от того, как он указан.

С документация:

следует реальные символические ссылки, только если они начинаются с " refs/": в противном случае это просто попробуйте прочитать их и обновить их как обычный файл.

так вот почему если вы говорите git update-ref master <value> он будет лечить master как имя файла и создайте его в .git.


Git 2.18 (Q2 2018) улучшает надежность обновления git-ref, потому что"git update-ref A B " должен гарантировать, что ref A еще не существует, когда B является нулевым OID, но эта проверка не была выполнена правильно для псевдо-ссылок вне refs / иерархии, например MERGE_HEAD.

посмотреть совершить db0210d, совершить 65eb8fc, совершить c0bdd65 (10 мая 2018) by Мартин Огрен (`).
Помог: Рафаэль Ascensão .
(слитый Junio C Hamano -- gitster -- на совершить 26597cb, 30 мая 2018)

refs: обрабатывать нулевой oid для псевдореф

согласно документации, возможно "указать 40' 0 ' или пустые строки <oldvalue> чтобы убедиться, что ref вы создаете не существует."
Но в коде для pseudorefs мы этого не реализуем, как показали добавленные неудачные тесты в предыдущий.
Если мы не читаем старого рефери, мы немедленно умираем. Но провал чтение на самом деле было бы хорошо, если бы нам дали нулевой oid.

С нулевым oid, позвольте -- и даже требуйте -- ref-чтение потерпеть неудачу. Это реализует "make sure that the ref ... does not exist" часть документация и исправления обоих неудачных тестов из предыдущей фиксации.

у нас есть strbuf err для сбора ошибок, давайте использовать его и сигнализируйте об ошибке звонящему вместо того, чтобы умирать.