Обмен одного файла в ветке git-репозитория - PullRequest
0 голосов
/ 30 октября 2019

У меня есть файл config.txt в данной ветке удаленного репозитория git.

Теперь у меня есть новая версия этого файла (вне любого репозитория git, только сгенерированный файл), и я хочусовершить это. Для этого мне нужно написать скрипт оболочки. Что было бы хорошим подходом для этого?

Нужна ли мне локальная копия всего репозитория git? Или это можно сделать более напрямую?

1 Ответ

1 голос
/ 30 октября 2019

Во-первых, помните, что Git действительно заботится о коммитах , и каждый коммит представляет собой полный снимок всех файлов. Более того, каждый коммит сделан из того, что есть в Git index в то время, когда вы запускаете git commit. git checkout данного коммита заполняет индекс этого коммита, одновременно заполняя рабочее дерево этими файлами (в их обычной форме), чтобы вы могли их видеть.

Таким образом, если вы хотитеДля создания нового коммита, в котором все файлы совпадают с предыдущим коммитом , за исключением для config.txt, который должен быть заменен оптом, необходимо:

  • заполнить индекс этими файлами
  • замените файл config.txt в индексе новым содержимым
  • зафиксируйте полученный индекс

Самый простой способ сделать это - получить хранилище -или его клон - с рабочим деревом в расположении W (некоторая директория / папка на вашем компьютере), в "чистом" состоянии (так что git status в W скажет nothing to commit, working tree clean). Затем в W выполните:

git checkout branchname

, которая заполняет индекс и рабочее дерево хранилища в W . Затем вы можете:

cp <path> config.txt

(где path - это новое сгенерированное содержимое), затем:

git add config.txt
git commit -m "replace config.txt with new generated config"

Если этот репозиторий скопирован из какого-либо другогоGit-репозиторий в другом месте, теперь вы можете git push новый коммит в этом другом Git-репозитории и попросить Git-репозиторий обновить его имя ветки, чтобы включить новый коммит (который, конечно, обычно помнит своего предшественника).

Помните, что этот git push может участвовать в гонках против других пользователей, которые также обновляют этот другой Git, поэтому может произойти сбой, если они обновят ветку другого Git. В этом случае вам, вероятно, следует в основном начать все сначала: обновить локальный клон, чтобы забрать их новые коммиты, жестко сбросить одну ветку, скопировать сгенерированный config.txt, добавить, зафиксировать и нажать. Если это не удается, перезапустите еще раз, пока это не будет успешным.

(Если существует ограничение, по которому именованная ветвь должна не быть обновлена ​​кем-либо еще в этот период времени, вы можетепропустите цикл перезапуска и повторных попыток и просто сообщите о любом сбое для диагностики человеком.)

Нужна ли локальная копия всего репозитория git?

Вам нужно достаточно репозитория Git, чтобы иметь возможность проверить целевую ветвь (таким образом, заполняя индекс и рабочее дерево), заменить один файл, git add, git commit и git push,Сколько "достаточно"? Ну, все, что вам действительно нужно, это один текущий кончик ветви этой названной ветви, так что достаточно мелкого клона глубиной 1. Следовательно, если у вас нет вообще нет репозитория, вы можете запустить цикл повтора с помощью:

git clone --depth 1 --single-branch -b <branch-name> <url> [<local-dir>]

, чтобы получить этот мелкий клон в любом каталоге. Если нажатие завершится неудачно и вы захотите создать цикл повторной попытки, вы можете просто git fetch в этом существующем мелком клоне обновить origin/<em>branch-name</em>, а затем использовать git reset --hard origin/<em>branch-name</em> для сброса при следующей попытке добавления / фиксации / нажатия. Тогда вам, вероятно, следует удалить этот репозиторий, поскольку мелкие клоны с одной веткой - это что-то вроде песколовки / смолки / любого другого любимого вами термина для других людей, которые сталкиваются с ними и не готовы к этому. все острые острые биты, которые присутствуют в мелких хранилищах и репозиториях с одной ветвью.

Или это можно сделать более напрямую?

Вместо того, чтобы делать все это на клиенте,в клоне и git push на сервере Git вы могли бы отправить вновь сгенерированный config.txt на сервер - в местоположение вне его клона , который, вероятно, --bare в любом случае - каким-то не-Git-методом (например, scp или rsync) и запустить что-то непосредственно на сервере . Это, конечно, предполагает, что у вас есть такой доступ к серверу.

Еслиу вас есть пустой репозиторий, который не имеет рабочего дерева, вы все равно можете сделать новый коммит, потому что даже пустой репозиторий имеет индекс. Вам просто нужно прочитать существующий коммит с ветвлением в индекс:

git read-tree <branch-name>

, а затем заменить этот один файл в индексе, используя git update-index--stdin или --cacheinfo), но сделатьпоэтому вам нужно будет использовать git hash-object -w для создания объекта blob из желаемого контента. Затем, обновив индекс, используйте git write-tree, чтобы написать новый объект дерева, затем используйте git commit-tree, чтобы построить фиксацию из результирующего объекта дерева, и, наконец, используйте git update-ref, чтобы обновить имя ветви, чтобы указать на новыйсовершить. Если ветвь может быть обновлена ​​с помощью git push, вам все равно понадобится повторный цикл или какой-либо метод блокировки ветки с помощью git push. Любой способ блокировки зависит от вас, возможно, с использованием хуков.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...