使用git hash-object构建git commit对象?

时间:2013-04-17 16:06:11

标签: git

如何使用git hash-object手动构建git commit对象? 我现在使用blob,它的文档说它可以使用-t构建不同的对象,但是你如何用它构建一个提交?

2 个答案:

答案 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/toname=file。如果离开,新文件在git - workdir的顶部称为“dummyfile”。

  • obid="$(git hash-object -w --stdin)"然后将包含从stdin读取的信息的对象存储到git存储库中,并将新对象的SHA(对象ID)存储在变量{{ 1}}。在示例中,内容为obid,后跟hellOw W0rld

  • NLgit 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
    

说明: