2013-04-17 3 views
2

Как я могу вручную создать объекты git commit, используя git hash-object? Теперь я работаю с blobs, и в его документации говорится, что он может создавать разные объекты, используя -t, но как вы строите фиксацию с этим?Построение git commit объектов с git hash-object?

+0

Вам нужно сделать несколько деревьев объектов в сделать объект фиксации. Вы можете использовать индексный файл и 'write-tree' или просто' mktree'. Вы можете использовать 'хэш-объект', если хотите, но мне кажется, что это очень сложно. –

+0

Знаете ли вы, как использовать хэш-объект для этого? Я знаю о существовании git commit-tree, но можете ли вы сделать это с git-хэш-объектом? – 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', это означает только, что оно отображается как' empfile' в 'git'-worktree.Таким образом, имя файла, используемого для 'git hash-object', не обязательно должно быть одинаковым для' git mktree'. – Tino

+0

Вы правы. Я исправляю это. –

0

В интересах читателя:

accepted answer from Arialdo Martini полностью верен и объясняет, как создать пустой репозиторий git с правильными командами сантехники. Обратите внимание, что его вариант работает и для репозиториев bare (вы можете создать emptyfile в git -dir без каких-либо плохих побочных эффектов).

Этот ответ здесь суммирует его на скрипт с незначительным изменением: содержимое файла берется из «stdin», и файл можно поместить в подкаталог рабочей строки.

Script 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/to и name=file. Если это не указано, новый файл называется «dummyfile» в верхней части git -workdir.

  • obid="$(git hash-object -w --stdin)" затем сохраняет объект с информацией, считанной из stdin в git репо и сохраняет ША (идентификатор объекта) нового объекта в переменной obid. В этом примере содержимое 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. 100644 является обычным файловым режимом. Если вы хотите создать исполняемые файлы, вам нужно 100755.

  • treeid="$( ...)" затем присваивает это к данному переменному treeid

  • if [ . = "$dir" ]; then git read-tree -i "$treeid"; это читает это вновь созданное дерево в область git ступенчатых для последующего совершения. Однако в этом случае файл должен быть непосредственно в файле git -workdir.

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

Примечания: