Как проверить, существует ли папка в теге git - PullRequest
1 голос
/ 15 марта 2020

Мне нужно набрать sh различных версий кода до git во время выпуска и выполнить откат к предыдущей версии в случае проблем.

Мы используем теги для выпуска.

Для Откат, я хотел бы проверить, существует ли папка с кодом в предыдущем теге.

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

Есть ли способ проверить, существует ли папка в теге git? Затем я хотел бы использовать возвращаемое значение для mt script.

1 Ответ

2 голосов
/ 15 марта 2020

Существует относительно прямой и простой ответ на вопрос, который вы не задали, а именно: просто запустите git cat-file -t <em>commit-specifier</em>:<em>path</em>. Если он говорит, что он существует и является объектом tree , указанный вами коммит содержит файлы, которые go будут помещены в папку с таким именем. Если он говорит, что это какой-то другой тип объекта, указанный вами коммит не содержит таких файлов: вместо него он имеет этот объект. Если это не удается полностью, указанный вами коммит не содержит ни одного объекта с таким именем. Следовательно:

objid="${tagname}:${path}"
objtype=$(git cat-file -t $objid 2>/dev/null) || objtype=none
case $objtype in
none) echo no such folder would be created;;
blob) echo the specified path holds a file rather than a folder;;
tree) echo a folder would be created and contain some files;;
commit) echo the specified path refers to a submodule;;
*) echo something went terribly wrong;;
esac

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

Отвечая на то, что вы спросили, а не на то, что, я думаю, вы хотели задать

Однако вопрос, который вы фактически задали, был:

Есть ли способ проверить, существует ли папка в теге git?

A тег - это просто имя - как правило, в соответствии с v2.1 или подобное - это относится к какому-либо объекту Git. Этот Git объект обычно является аннотированным теговым объектом или commit . Если имя тега относится непосредственно к коммиту, Git называет это облегченным тегом . Если имя тега относится к аннотированному объекту тега, Git называет это аннотированным тегом . Затем объект аннотированного тега ссылается на другой объект.

В некоторых случаях целевой объект объекта аннотированного тега является другим аннотированным тегом. Если это так, Git может прочитать этот второй теговый объект, который ссылается на другой объект. Этот объект может быть другим аннотированным теговым объектом: если так, Git продолжает читать и следовать, пока в конечном счете некоторый аннотированный теговый объект не ссылается на что-то иное, чем аннотированный теговый объект. Другими словами, в то время как аннотированный теговый объект может «продолжать летать», указывая на другой, в конечном итоге все такие цепи «падают на землю». Git вызывает этот процесс, следуя объектам тегов, пока Git не достигнет объекта, не являющегося тегом, очистит тег . Очистка тега в конечном итоге приводит к одному из оставшихся возможных типов объектов: commit , tree или blob .

Так что технически нет В теге всегда хранится папка any file или . Он просто называет commit . И, к сожалению, commit не хранит папку. К счастью, это не важно!

Почему я думаю, что вы хотели спросить что-то еще

Техническая причина, по которой Git не хранит папки, заключается в том, что он делает новые коммиты из index и индекс не может хранить имена папок. 1 Однако он принимает имена files ' индекса, которые могут быть довольно длинными и могут содержать прямые косые черты (например, , dir/sub/file.ext) и разбить их на составные части . Поэтому, когда index содержит файл с именем dir/sub/file.ext, Git создаст объект дерева с именем dir, ссылающийся на объект дерева с именем sub, ссылающийся на объект BLOB-объекта с именем file.ext , Мы посмотрим, как это работает через мгновение.

Возвращаясь к коммитам, объект фиксации содержит коммит. Фиксация представляет собой полный и полный снимок вашего источника. Внутренне это делается путем указания (удерживая идентификатор ha sh) объекта tree . Вот, например, фактический коммит в репозитории Git для Git:

$ git rev-parse HEAD
51ebf55b9309824346a6589c9f3b130c6f371b8f
$ git cat-file -p HEAD | sed 's/@/ /'
tree 7db7271b4def298424e57b0a04129f6a929955d0
parent f97741f6e9c46a75b4322760d77322e53c4322d7
author Junio C Hamano <gitster pobox.com> 1581974501 -0800
committer Junio C Hamano <gitster pobox.com> 1581974539 -0800

The sixth batch for 2.26

Signed-off-by: Junio C Hamano <gitster pobox.com>

Обратите внимание на первую строку, tree 7db7271b4def298424e57b0a04129f6a929955d0. Это снимок, сохраненный в коммите 51ebf55b9309824346a6589c9f3b130c6f371b8f.

Объект дерева содержит массив из трех кортежей: , Имя компонента является частью имени пути. Режим является одним из небольшого набора разрешенных восьмеричных чисел, представляющих поддеревья, объекты коммитов (gitlinks) или объекты BLOB-объектов (содержимое файлов и символов c link). Если используется режим объекта дерева или блоба, идентификатор ha sh в записи должен быть идентичным объекту Git, содержащему объект дерева или блоба соответственно.

Вот часть того, что находится в tree объекте 7db7271b4def298424e57b0a04129f6a929955d0:

$ git cat-file -p 7db7271b4def298424e57b0a04129f6a929955d0
[snip]
100644 blob 536e55524db72bd2acf175208aef4f3dfc148d42    COPYING
040000 tree d12f433f975c365f2516022fd6ba597548a12a55    Documentation
100755 blob 616d5a6404e4f1a6550b2aca89488889dbe6d34f    GIT-VERSION-GEN
100644 blob 22c364f34f573c615d968a85374ba2c429b7fabd    INSTALL
100644 blob d38b1b92bdb2893eb4505667375563f2d6d4086b    LGPL-2.1
[snip]

Обратите внимание, как обычные файлы, такие как COPYING и GIT-VERSION-GEN, хранятся как blob ссылки на объекты в этом дереве верхнего уровня. Однако Documentation не является именем какого-либо файла. Когда этот коммит извлекается, некоторые файлы будут иметь имена, которые начинаются с Documentation/. Вот немного из того, что находится в дереве d12f433f975c365f2516022fd6ba597548a12a55:

$ git cat-file -p d12f433f975c365f2516022fd6ba597548a12a55
[snip]
100644 blob aa828dfdc44a856c8bdd8b0826defeb398113bcc    MyFirstObjectWalk.txt
040000 tree 467d9eb934bfbb8ff63f5d239b2d4c975ab8e9b9    RelNotes
100644 blob 4515cab5193ddf354a461aafb1b68dcc1ef2932e    SubmittingPatches
[snip]

Это показывает нам, что когда этот коммит извлечен, и у вас есть несколько файлов для работы, один из этих файлов будет называться Documentation/MyFirstObjectWalk.txt и один будет назван Documentation/SubmittingPatches. Так как есть также поддерево с именем RelNotes, должны быть файлы, имена которых начинаются с Documentation/RelNotes/.


1 Самое близкое значение индекса заключается в том, что оно может хранить gitlink имен. У Gitlinks есть режим 160000, который вы можете выбрать, используя ИЛИ символическую ссылку 120000 с древовидным режимом 040000. Обидно, что вы не можете получить индексную запись режима 040000, поскольку будет позволять Git хранить пустые папки.


Что все это означает

Если мы находим объект коммита ha sh ID , например, по git rev-parse v2.1, если есть тег с именем v2.1, мы можем проверить объект фиксации. Он будет иметь запись tree.

Затем мы можем проверить объект tree . Если у него есть поддерево, как у вышеприведенного есть Documentation, то мы можем предположить , что в этом коммите должны быть файлы, имя которых начинается с Documentation/. Чтобы извлечь такой коммит, Git потребуется создать папку с именем Documentation.

В коммите эта папка не содержится . 2 Но извлечение фиксация действительно создает такую ​​папку в вашем рабочем дереве. Вероятно, это то, что вас волнует: извлечение коммита (с git checkout) или перемещение к нему (с git reset --hard), например, создаст или, возможно, удалит 3 такая папка в вашем рабочем дереве.

Проверка наличия этого объекта дерева в любом заданном коммите Этот способ, проверяя каждый уровень по одному шагу за раз, болезненный. Но команда git rev-parse, которая может превратить любое действительное имя в Git объект с sh ID, делает это легко. Таким образом, хотя вы можете запустить git rev-parse <em>hash</em>, чтобы узнать, является ли hash действительным Git идентификатором объекта, вы также можете запустить git rev-parse <em>hash</em>:<em>path</em>, чтобы проверить, может ли hash превратиться в объект commit и затем проанализировать путь к нему. Это имя пути будет автоматически ссылаться на некоторый объект Git; git rev-parse будет выдавать свой га sh идентификатор.

Хотя мы не хотим, чтобы га sh ID . Это просто говорит нам, что некоторый объект существует, не сообщая нам, какой тип объект имеет. Чтобы найти объекта типа нам нужно git cat-file -t. Он берет имя или идентификатор любого объекта и сообщает нам тип - или выдает ошибку, если идентификатор недействителен:

$ git cat-file -t d12f433f975c365f2516022fd6ba597548a12a55
tree
$ git cat-file -t 616d5a6404e4f1a6550b2aca89488889dbe6d34f
blob
$ git cat-file -t a123456
fatal: Not a valid object name a123456

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

$ git cat-file -t v2.23.0
tag

Говоря Git - очистить тег, используя ^{}, мы находим целевой объект:

$ git cat-file -t v2.23.0^{}
commit

и говорим Git заглянуть внутрь этого При фиксации имени пути мы получаем:

$ git cat-file -t v2.23.0:Documentation
tree

, что более информативно, чем:

$ git rev-parse v2.23.0:Documentation
b55461e880f78ae8253c8be287476cbbddd44957

, так что это путь к go.


2 Если вы называете объект дерева"папкой", вы можете утверждать, что коммит содержит папку, но это не совсем так, как на самом деле работает Git. Объект поддерева может существовать в коммите, только если в нем есть files . Иногда раздражает, что это так, но это так.

3 Когда git checkout движется от полностью проверенного коммита, который содержит, например, sub/one и sub/two для коммита, содержащего нет файлов, которые требуются ОС, которые будут помещены в папку с именем sub/, Git, конечно, удалит эти два файла из рабочего дерева. Они находятся в индексе и рабочем дереве прямо сейчас, но они не в целевом коммите, поэтому они должны go удалиться. Удалив оба файла, Git также удалит пустую папку sub/ из рабочего дерева. Если папка sub/ не является пустой, из-за наличия неотслеживаемых файлов, Git не удалит ее. Вот теперь все это работает: Git создает папки по требованию ОС, чтобы они существовали, чтобы файлы * go были в них. Git удаляет их, когда очищает, но не, если не очищает. В противном случае Git просто их не трогает.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...