如果提供给散列对象的文件名参数与原始文件名不同,则无法创建提交
Cannot create commit if the filename argument given to hash-object differs from the original filename
我正在研究 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-1 赋给了 blob
对象,它只包含文件的内容。
让我们继续写树:
$ git write-tree
abbb70126eb9e77aaa65efbe0af0330bda48adf7
$ git cat-file -p abbb70126eb9e77aaa65efbe0af0330bda48adf7
100644 blob 2d1b0d728be34bfd5e0df0c11b01d61c77ccdc14 orange.txt
$ git cat-file -p 2d1b0d728be34bfd5e0df0c11b01d61c77ccdc14
I'm an apple
让我们通过创建指向此树的提交来完成此操作:
$ 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
我是不是漏掉了什么?
您创建了提交,但没有更新任何引用以指向它。您仍然签出到未出生的 master
分支。 (请记住,默认情况下 git log
显示已签出内容的历史记录;即使您告诉它显示 "all",它也倾向于显示可从 refs 访问的内容。)
你没有在上面显示它,但是当你发出 commit-tree
时,它应该已经将哈希打印到标准输出(并且在我按照你的步骤进行的测试中,它确实如此)。所以然后将其称为 <commit-hash>
你可以说
git merge <commit-hash>
不断变化的文件名主要是转移注意力。在这种情况下,索引和数据库都不包含知道 apple.txt
的对象,因此 apple.txt
只是您注意到的工作树上的一个未跟踪文件。
Update - 作为附加说明,您正在创建没有父级的新提交,这是有道理的,因为您的回购中还没有任何提交(如果我是正确阅读你的场景)。一般来说,如果向现有(并已检出)分支添加新提交,您需要提供类似 -p HEAD
的参数 - 即使这样 commit-tree
单独的命令也不会更新分支。
如果您想避免合并(支持较低级别的命令),另一种选择是 git update-ref
,如
git update-ref refs/heads/master 50b7
(这有点危险,因为假设您知道自己在做什么,即使您犯了错误,也更有可能做错事...但这就是管道命令。)
你还需要运行
git update-ref refs/heads/master a4386cb82e1f6d1755e47ace1f378df35df31967
这会将您的新提交注册为当前 HEAD
我正在研究 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-1 赋给了 blob
对象,它只包含文件的内容。
让我们继续写树:
$ git write-tree
abbb70126eb9e77aaa65efbe0af0330bda48adf7
$ git cat-file -p abbb70126eb9e77aaa65efbe0af0330bda48adf7
100644 blob 2d1b0d728be34bfd5e0df0c11b01d61c77ccdc14 orange.txt
$ git cat-file -p 2d1b0d728be34bfd5e0df0c11b01d61c77ccdc14
I'm an apple
让我们通过创建指向此树的提交来完成此操作:
$ 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
我是不是漏掉了什么?
您创建了提交,但没有更新任何引用以指向它。您仍然签出到未出生的 master
分支。 (请记住,默认情况下 git log
显示已签出内容的历史记录;即使您告诉它显示 "all",它也倾向于显示可从 refs 访问的内容。)
你没有在上面显示它,但是当你发出 commit-tree
时,它应该已经将哈希打印到标准输出(并且在我按照你的步骤进行的测试中,它确实如此)。所以然后将其称为 <commit-hash>
你可以说
git merge <commit-hash>
不断变化的文件名主要是转移注意力。在这种情况下,索引和数据库都不包含知道 apple.txt
的对象,因此 apple.txt
只是您注意到的工作树上的一个未跟踪文件。
Update - 作为附加说明,您正在创建没有父级的新提交,这是有道理的,因为您的回购中还没有任何提交(如果我是正确阅读你的场景)。一般来说,如果向现有(并已检出)分支添加新提交,您需要提供类似 -p HEAD
的参数 - 即使这样 commit-tree
单独的命令也不会更新分支。
如果您想避免合并(支持较低级别的命令),另一种选择是 git update-ref
,如
git update-ref refs/heads/master 50b7
(这有点危险,因为假设您知道自己在做什么,即使您犯了错误,也更有可能做错事...但这就是管道命令。)
你还需要运行
git update-ref refs/heads/master a4386cb82e1f6d1755e47ace1f378df35df31967
这会将您的新提交注册为当前 HEAD