Ответ DileepNimantha в основном правильный (он пропускает шаг, по крайней мере, в то время, когда я пишу это), но есть несколько потенциально более простых способов.Мы вернемся к самому простому позже;давайте начнем с того, что мы действительно делаем.Я добавлю, что отсутствующим шагом является запуск git fetch
и git read-tree
(см. Ниже) после git remote add ...
.Есть также предположение, что текущая ветвь master
правильная.
Фундаментальная проблема - это та, которую вы определили: у вас есть пустое хранилище (с core.bare = true
, git init --bare
и т. Д.), Котороеследовательно, у него нет рабочего дерева.
Чтобы сделать новый коммит в любом Git-репозитории, вам технически не нужно рабочее дерево вообще.Вам нужно, чтобы index (также известный как staging-area или иногда cache ), связанный с этим хранилищем, имел правильное содержимое файла.Однако стандартный способ сделать это - использовать git add <em>file1</em> <em>file2</em> ...
, который копирует указанные файлы из вашего рабочего дерева в ваш индекс, перезаписывая старые версии этих файлов в индексе.Это, конечно, требует рабочего дерева.
Пустой репозиторий, несмотря на отсутствие рабочего дерева, все еще имеет индекс.Вот как мы можем обойти отсутствие рабочего дерева.
Вы можете заполнить индекс из определенного коммита, такого как подсказка master
, используя git read-tree
:
$ git read-tree master
Затем можно заменить одну из записей индекса из файла в файловой системе.В этом случае я обновил sig.py
, распаковав его в файл в файловой системе, который сейчас находится в / tmp, а затем отредактировал его там:
$ git hash-object -w -t blob /tmp/sig.py
b6a42a1dd3fff08aa4bed6b054b310f69ed518c1
Теперь необходимо создать git ls-files
этап записи для этого файла.Старый:
$ git ls-files --stage sig.py
100644 7e49ad4f1042b14e088571a091a7b9f7d1010b4c 0 sig.py
Нам не нужно использовать номер этапа, так как git update-index
позволяет нам его пропустить, поэтому мы можем напечатать новый хэш вместе с остальной соответствующей информацией:
$ printf '%s %s %s\t%s\n' 100644 blob \
b6a42a1dd3fff08aa4bed6b054b310f69ed518c1 sig.py | \
git update-index --index-info
Я разделил это на три строки, две с обратной косой чертой-новой строкой, для публикации длины.На самом деле это все одна команда, но когда она выражается таким образом, как ввод оболочки, она будет работать так же хорошо.Обратите внимание, что новый хэш blob - это тот, который мы получили, записав новый обновленный файл в хранилище.(Примечание: у нас есть около 14 дней, чтобы закончить нашу работу после того, как мы начнем этот процесс, прежде чем git gc
объявит, что наш вновь созданный объект BLOB-объекта не используется, и, следовательно, удалит его.)
Теперь нам нужнозапишите индекс в виде дерева объекта:
$ git write-tree
e92275076a62ca850b0bda3f6c3603632b4a6cce
и затем сохраните это дерево как объект фиксации.Давайте сделаем этот новый коммит, который мы добавим после текущей подсказки master
:
$ git commit-tree -p master \
-m 'make signal handler work in py2k and py3k' \
e92275076a62ca850b0bda3f6c3603632b4a6cce
Выполнение этого произвело для меня хеш коммита:
e068bdfce2fd992dc396cb4969327ef5c4d39a43
МыТеперь нужно сделать какое-нибудь имя ветки, возможно, новое, сослаться на этот хеш коммита.Я буду использовать новый вместо того, чтобы обновлять master
вместо:
$ git branch fix-signal e068bdfce2fd992dc396cb4969327ef5c4d39a43
Теперь мы можем видеть, сработало ли это, запустив git log
в этом голом хранилище:
$ git log --oneline --decorate -n 2 fix-signal
e068bdf (fix-signal) make signal handler work in py2k and py3k
11ae6ca (HEAD -> master) add run-checks script
Давайте рассмотрим изменение как патч:
$ git show fix-signal
[snip]
index 7e49ad4..b6a42a1 100644
--- a/sig.py
+++ b/sig.py
@@ -5,7 +5,10 @@ import sys
import time
def signal_handler(signum, frame):
- os.write(1, bytes('caught sig %d\n' % signum, 'iso8859-1'))
+ if str is not bytes:
+ os.write(1, bytes('caught sig %d\n' % signum, 'iso8859-1'))
+ else:
+ os.write(1, 'caught sig %d\n' % signum)
def catch_by_sig():
old_int = signal.signal(signal.SIGINT, signal_handler)
Но это действительно --bare
репозиторий:
$ git status
fatal: This operation must be run in a work tree
Упрощение
git
команда front-end принимает много опций, которые появляются перед глаголом.Например, если ваше извлеченное рабочее дерево на сервере находится в /tmp/work
, вы можете на сервере cd
в свой репозиторий Git:
$ cd ...
и затем запустить:
$ git --work-tree=/tmp/work status
и получите вывод статуса. Обратите внимание, что git status
сравнивает фиксацию HEAD с текущим содержимым индекса, а затем текущим содержимым индекса с рабочим деревом. Поскольку ваш основной Git-репозиторий здесь является --bare
, его индекс может не соответствовать содержимому вашего каталога /tmp/work
.(В зависимости от того, как у вас на сервере развертываются нажатия, индекс для этого Git-репозитория может быть не пустым. Вы должны решить, волнует ли вас, что в нем находится.)
При необходимости вы можете использовать операцию git read-tree
, как мы делали в более длинной форме выше, чтобы заполнить индекс из некоторого конкретного коммита.Вы можете назвать коммит по его имени ветки, как я делал выше, или по его хэш-идентификатору: ключ заключается в заполнении индекса из коммита, который в данный момент развернут в области развертывания.
Теперь, когда индекс заполнен так, чтобы соответствовать (в основном) области развертывания, за исключением измененных файлов, вы можете запустить:
git --work-tree=/tmp/work add file1.ext file2.ext
, например, чтобы добавить эти файлы из рабочейдерево (вы будете делать это, когда "cd" -ed в Git-репозиторий).Затем вы можете запустить:
git --work-tree=/tmp/work commit
как обычно. Обратите внимание, что это будет зафиксировано в текущей ветви, , т. Е. Той, к которой HEAD
присоединен в хранилище.Это, вероятно, правильно из-за любого сценария развертывания, который вы используете.
По сути, каждый раз, когда вы запускаете команду Git, вы говорите: игнорируйте настройку core.bare
, рабочее дерево поверхв этом другом пути. На самом деле, вероятно, именно так работает ваш хук развертывания во время push-операции.
Я не рекомендую делать это как обычную практику - вы получаете все расходыПозволяет отправлять в не-пустое хранилище, без каких-либо преимуществ, так что вы могли бы просто настроить не-пустое хранилище, вместо того, чтобы заниматься этим.Но как быстрое решение проблемы чрезвычайной ситуации, оно работает.