Невозможно создать коммит, если аргумент имени файла, данный для hash-объекта, отличается от исходного имени файла - PullRequest
0 голосов
/ 22 мая 2018

Я играю с сантехническими командами git, чтобы лучше понять его внутренние механизмы.Я пытаюсь воспроизвести коммит без использования команды git commit.Давайте создадим blob:

$ git init
$ echo "I'm an apple" > apple.txt
$ git hash-object -w apple.txt
2d1b0d728be34bfd5e0df0c11b01d61c77ccdc14

Теперь давайте добавим его в индекс, но с другим именем файла :

$ git update-index --add --cacheinfo 100644 2d1b0d728be34bfd5e0df0c11b01d61c77ccdc14 orange.txt

Вот вывод git status:

$ git status
On branch master

Initial commit

Changes to be committed:
  (use "git rm --cached <file>..." to unstage)

    new file:   orange.txt

Changes not staged for commit:
  (use "git add/rm <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

    deleted:    orange.txt

Untracked files:
  (use "git add <file>..." to include in what will be committed)

    apple.txt

Что здесь происходит?

apple.txt все еще существует, но не отслеживается, что мне кажется нормальным, поскольку я передал SHA-1blob объект, который содержит только содержимое файла.

Давайте продолжим и напишем дерево:

$ git write-tree
abbb70126eb9e77aaa65efbe0af0330bda48adf7
$ git cat-file -p abbb70126eb9e77aaa65efbe0af0330bda48adf7
100644 blob 2d1b0d728be34bfd5e0df0c11b01d61c77ccdc14    orange.txt
$ git cat-file -p 2d1b0d728be34bfd5e0df0c11b01d61c77ccdc14
I'm an apple

Давайте закончим эту операцию, создавcommit, указывающий на это дерево:

$ echo "Add fruit" | git commit-tree abbb70126eb9e77aaa65efbe0af0330bda48adf7
57234c35c0d58713d2b4f57b695043e5331afe58
$ git cat-file -p a4386cb82e1f6d1755e47ace1f378df35df31967
tree abbb70126eb9e77aaa65efbe0af0330bda48adf7
author Gregoire Borel <gregoire.borel@nxxx.xx> 1527001408 +0200
committer Gregoire Borel <gregoire.borel@xxx.xx> 1527001408 +0200

Add fruit

Теперь, если я запускаю git status, вывод будет таким же, как указано выше.Зачем?Кроме того, кажется, что коммит не был создан:

$ git log
fatal: your current branch 'master' does not have any commits yet

Я что-то пропустил?

Ответы [ 2 ]

0 голосов
/ 22 мая 2018

вам все еще нужно запустить

git update-ref refs/heads/master a4386cb82e1f6d1755e47ace1f378df35df31967

, при этом ваш новый коммит будет зарегистрирован как текущий HEAD

0 голосов
/ 22 мая 2018

Вы создали коммит, но не обновили ни одного ссылки, чтобы указать на него.Вы все еще проверены на нерожденную ветку master.(Помните, по умолчанию git log показывает историю того, что было извлечено; и даже когда вы говорите, что оно показывает «все», оно стремится только к тому, что достижимо из ссылок.)

Вы не показывали это выше,но когда вы выдавали commit-tree, он должен был напечатать хеш для стандартного вывода (и в моем тесте, следуя вашим шагам, это так).Тогда, ссылаясь на это как <commit-hash>, вы можете сказать

git merge <commit-hash>

. Изменяющееся имя файла - это в основном красная сельдь.Ни индекс, ни база данных никогда не содержат объект, который знает apple.txt в этом сценарии, и поэтому apple.txt - это просто неотслеживаемый файл в рабочем дереве, как вы заметили.


Обновление - в качестве дополнительной заметки вы создаете новый коммит без родителя, что имеет смысл, поскольку в вашем репо еще нет коммитов (если я правильно читаю ваш сценарий).В общем, если вы добавляете новый коммит в существующую (и извлеченную) ветвь, вам нужно будет указать аргумент, такой как -p HEAD - и даже тогда одна команда commit-tree не будет обновлять ветку.

Если вы хотите избежать слияния (предпочитая команды более низкого уровня), альтернативой будет git update-ref, как в

git update-ref refs/heads/master 50b7

(Это немного опаснее, так как с большей вероятностьюнеправильно, если вы знаете, что делаете, даже если допустили ошибку ... Но такова природа сантехнических команд.)

...