2013-04-17 100 views
2

我該如何手動構建使用git散列對象的git commit對象? 我現在可以使用blob,它的文檔說它可以使用-t構建不同的對象,但是如何使用-t構建一個提交?用git hash-object構建git commit對象?

+0

你需要做一些樹對象創建一個提交對象。你可以使用索引文件和'write-tree'或者'mktree'。如果你真的想要,你可以使用'hash-object',但對我來說似乎很麻煩。 –

+0

你知道如何使用散列對象來做到這一點嗎?我知道git commit-tree的存在,但是你可以使用git hash-object來做到這一點嗎? – user2291590

+0

您只需將一個有效的樹管道輸送給它,就像您使用其他任何對象(如blob)一樣。 –

回答

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\[email protected]\n2013 12:20:15 +0200\ncommittername\[email protected]\n2013 10:13:15 +0200" | git commit-tree ${tree}` 

git update-ref refs/heads/master ${commit} 

要驗證該腳本創建一個提交包含一個空文件,運行:

git checkout -- 
git log --oneline 
#2abbdc2 yourname [email protected] 2013 12:20:15 +0200 committername [email protected] 

編輯:固定的和改進的

+0

是「\ tempfile」還是「\ temtyfile」? – qbolec

+0

@qbolec'\ t'代表'TAB'字符,所以是'\ temptyfile'。然而,將'\ tempfile'錯誤地表示爲'\ tempfile',這意味着它在'git'-worktree中顯示爲'empfile'。所以用於'git hash-object'的文件名不一定需要與'git mktree'相同。 – Tino

+0

你說得對。我正在解決這個問題。 –

0

爲了讀者的利益:

accepted answer from Arialdo Martini是完全正確的,並說明如何創建一個空的git回購適當管道命令。請注意,他的變型適用於bare倉庫,太(你可以在git -dir創建emptyfile沒有不良副作用)。

這裏的答案將其歸納爲一個小小的調整腳本:該文件的內容取自「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 worktree和initiailizes它。它以第一個參數命名(這裏是newgitdir),假定它命名爲現有路徑中不存在的目錄。

  • dir="$(dirname "$2")"name="$(basename "${2:-dummyfile}")"提取路徑,第二個參數,它定義了想要的文件名的名稱的一部分。該路徑與創建的git -workdir相關。請注意,該參數不得以/開頭,否則命令將失敗。這裏dir=path/toname=file。如果離開,新文件在git -workdir的頂部被稱爲「dummyfile」。

  • ​​然後存儲與在變量obidstdin讀入新對象的git回購並存儲SHA(對象ID)的信息的對象。在該示例中,內容是hellOw W0rld,後跟NL

  • git mktree < <(printf '100644 blob %q\t%q\n' "$obid" "$name")幾乎與printf '100644 blob %q\t%q\n' "$obid" "$name" | git mktree相同,並創建一個合適的git-tree。 100644是通常的文件模式。如果你想創建可執行文件,你需要在這裏100755

  • treeid="$( ...)"然後分配給這個給定的變量treeid

  • if [ . = "$dir" ]; then git read-tree -i "$treeid";這讀取這個新創建的樹到git臨時區域後提交。但是,這種情況下,該文件應該直接在git-worksdir中。

  • else git read-tree --prefix="$dir/" -i "$treeid"; fi是相同的情況下,當你想把它放到git -workdir的子目錄中。好的是,git會自動爲您創建所有中間目錄節點。 (可悲--prefix="./"產生錯誤。)

  • git commit -m "${3:-automatic commit}"然後使用公知的提交來創建提交

  • git reset --hard然後同步的git -worktree與最新提交。

更改爲bare變種:

  • 一切工作類似,只不過git commit(這需要一個WORKDIR)和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" 
    

備註: