这很可能使用git 内部命令。请注意以下命令,因为这些命令会干扰 git 用来表示文件结构的文件,如果使用不当,可能会导致损坏或不正确的状态。
这将仅在创建单个文件之后进行,其余的将遵循类似的过程。所有这些命令都从repo.git
提到的文件夹运行,该文件夹被假定为--bare
存储库:
> cd /home/userX/somewhere
第一步是创建包含您要提交的文件的 git 对象。此命令将在 git 对象存储中创建文件的压缩副本。这个副本是不可避免的,因为它是 git 需要保留文件版本的内部副本:
> git hash-object -w /home/userX/whatever/wrapper/folder_A/file_1
cafebabe00000000000000000000000000000000
打印的散列是为存储而创建的对象file_1
。哈希当然是虚构的,因为它取决于文件的实际内容。
为了创建file_1
要定位的子文件夹,您需要为每个子文件夹级别创建一个树对象。注意创建的哈希是如何用于下一个子文件夹树的:
> echo -e "100644 blob cafebabe00000000000000000000000000000000\tfile_1" | git mktree
1111face11111111111111111111111111111111
> echo -e "040000 tree 1111face11111111111111111111111111111111\tfolder_a" | git mktree
2222face22222222222222222222222222222222
最后一个散列是将添加到当前树的散列。如果在--bare
repo 中工作,我们需要首先创建一个干净的索引。如果您在普通存储库中工作,则可以跳过此步骤,因为已经有索引文件,只需确保git status
显示干净状态即可。
在--bare
repo 中不应该有索引文件,但以防万一,删除它:
> rm index
为了创建一个干净的索引文件,我们添加了我们想要提交的分支的内容,我们假设master
. 此命令将打印当前存在的树的内容,master
并将其设置为当前索引:
> git cat-file -p master^{tree} | git update-index --index-info
现在有了一个干净的索引,我们添加了包含指向我们手动添加的文件的树的子目录。read-tree
将获取给定的树哈希并将其作为子文件夹添加到当前索引中,如下所述--prefix
:
> git read-tree --prefix=blah 2222face22222222222222222222222222222222
然后我们创建另一个代表索引当前状态的树。write-tree
将从当前索引中读取并从中生成树哈希:
> git write-tree
deadbeafaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
最后一个散列是我们将用来创建提交的散列:
> echo "at last a commit" | git commit-tree deadbeafaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -p master
baddcafe11111111111111111111111111111111
最后但同样重要的是,我们更新master
以指向新的提交:
> git branch --force master baddcafe11111111111111111111111111111111
有了这个,我们设法将一个文件添加到 git 中,而无需将其复制到工作区。所有这些步骤都是做什么git add
和git commit
最终做什么。通过 git 内部命令复制它们最终需要大量工作,而且很容易发生意外。如果你真的需要小心处理这个线程并了解 git 为你处理的底层结构,以便你可以使用它并修改它。