如何使用git hash-object手动构建git commit对象? 我现在使用blob,它的文档说它可以使用-t构建不同的对象,但是你如何用它构建一个提交?
答案 0 :(得分:3)
以下是一个完整且有效的脚本示例,它创建了一个commit
对象而没有运行git commit
:
mkdir project
cd project
git init
hash=`echo -n "" | git hash-object -w --stdin`
tree=`echo -e "100644 blob ${hash}\temptyfile" | git mktree`
commit=`echo -e "yourname\nyour@email.com\n2013 12:20:15 +0200\ncommittername\ncommitter@email.com\n2013 10:13:15 +0200" | git commit-tree ${tree}`
git update-ref refs/heads/master ${commit}
要验证脚本是否创建了包含空文件的提交,请运行:
git checkout --
git log --oneline
#2abbdc2 yourname your@email.com 2013 12:20:15 +0200 committername committer@email.com
编辑:修复和改进
答案 1 :(得分:1)
为了读者的利益:
accepted answer from Arialdo Martini完全正确,并解释了如何使用正确的管道命令创建一个空的git
repo。请注意,他的变体也适用于bare
存储库(您可以在emptyfile
- dir中创建git
,但没有不良副作用。)
这里的答案总结为一个带有小调整的脚本:文件的内容取自“stdin”,文件可以放在工作树的子目录中。
脚本git-init-with-file-from-stdin.sh new-git-workdir filename 'commit message'
:
#!/bin/bash
mkdir "$1" &&
cd "$1" &&
git init &&
dir="$(dirname "$2")" &&
name="$(basename "${2:-dummyfile}")" &&
obid="$(git hash-object -w --stdin)" &&
treeid="$(git mktree < <(printf '100644 blob %q\t%q\n' "$obid" "$name"))" &&
if [ . = "$dir" ]; then git read-tree -i "$treeid";
else git read-tree --prefix="$dir/" -i "$treeid"; fi &&
git commit -m "${3:-automatic commit}" &&
git reset --hard
解释了电话
./git-init-with-file-from-stdin.sh newgitdir path/to/file <<< "hellOw W0rld"
mkdir "$1"
,cd "$1"
,git init
创建新的git
工作树并对其进行初始化。它以第一个参数(此处为newgitdir
)命名,假定它在现有路径中命名一个不存在的目录。
dir="$(dirname "$2")"
,name="$(basename "${2:-dummyfile}")"
提取第二个参数的路径和名称部分,它定义了所需的文件名。该路径相对于创建的git
- workdir。请注意,此参数不能以/
开头,否则命令将失败。这里dir=path/to
和name=file
。如果离开,新文件在git
- workdir的顶部称为“dummyfile”。
obid="$(git hash-object -w --stdin)"
然后将包含从stdin
读取的信息的对象存储到git
存储库中,并将新对象的SHA(对象ID)存储在变量{{ 1}}。在示例中,内容为obid
,后跟hellOw W0rld
。
NL
与git mktree < <(printf '100644 blob %q\t%q\n' "$obid" "$name")
几乎相同,并创建了一个合适的git-tree。 printf '100644 blob %q\t%q\n' "$obid" "$name" | git mktree
是通常的文件模式。如果要创建可执行文件,则需要100644
此处。
100755
... treeid="$(
然后将其分配给给定变量)"
treeid
这会将此新创建的树读入if [ . = "$dir" ]; then git read-tree -i "$treeid";
暂存区域以供稍后提交。但是,对于这种情况,该文件应直接在git
- workdir。
git
- workdir的子目录中时, else git read-tree --prefix="$dir/" -i "$treeid"; fi
是相同的。好的是,git
会自动为您创建所有中间目录节点。 (遗憾的是git
会产生错误。)
--prefix="./"
然后使用众所周知的提交来创建提交
git commit -m "${3:-automatic commit}"
然后将git reset --hard
- 工作树与最新提交同步。
git
变体的更改:
除了bare
(这需要一个workdir)和git commit
(你不需要它)之外,一切都很相似。
替换
git reset
与
git init &&
也替换
git init --bare &&
与接受的答案中所见的序列相似:
git commit -m "${3:-automatic commit}" &&
git reset --hard
说明:
这里需要commitid="$(git commit-tree "$(git write-tree)" <<< "${3:-automatic commit}")" &&
git update-ref "refs/heads/master" "$commitid"
,也就是it works for Windows 10