Распространяются ли правила git update-index --assume-неизмененные на клиентов по запросу?
Есть случаи, когда я не могу использовать .gitignore
файл, в противном случае, на git push
, критические файлы удаляются с пульта. В этих случаях я применяю git update-index --assume-unchanged <file>
к файлам, которые я хочу игнорировать.
После применения предполагаемых неизменных правил и вызова git push
Будут ли эти правила присоединены к удаленной ветви, чтобы все последующие извлечения (от других клиентов) наследовали их? Или эти клиенты также должны запустить git update-index --assume-unchanged <file>
Команды индивидуально на своих машинах?
Если команды не наследуются - кто-нибудь ранее писал для этого хук сервера? Вместо того, чтобы требовать, чтобы все нынешние и будущие клиенты защитились от этого?
2 ответа
Индекс является локальным для вашей рабочей станции, любые внесенные вами изменения не распространяются на другие клоны того же пульта.
(обновлено, после того, как вопрос был обновлен)
Файл.gitignore
Есть случаи, когда я не могу использовать файл.gitignore, иначе при git push критические файлы удаляются с удаленного компьютера.
Это неправда. Файл git ignore не влияет на файлы, которые уже отслеживаются в хранилище. Если вы добавите файл в .gitignore
после того, как оно будет совершено, оно останется в хранилище; это не будет очищено. На самом деле, он ведет себя так, как будто его вообще не игнорируют.
Вы можете легко проверить это во временном хранилище:
$ mkdir -p /tmp/repo
$ cd /tmp/repo
$ git init
Initialized empty Git repository in /tmp/repo/.git/
$ echo red > a.txt
$ git commit -am '1'
1 file changed, 1 insertion(+)
create mode 100644 a.txt
$ echo a.txt > .gitignore
$ echo b.txt >> .gitignore
$ git commit -am '2'
1 file changed, 2 insertions(+)
create mode 100644 .gitignore
Хранилище теперь содержит два файла: a.txt
а также .gitignore
, Оба ведут себя нормально, что вы можете увидеть при клонировании:
$ cd ..
$ git clone file://repo repo2
$ ls -A repo2
.git .gitignore a.txt
$ cd repo
Если мы изменим оба игнорируемых файла и запрос git status
мы увидим что a.txt
рассматривается как измененный, несмотря на то, что был gitignored. Мы можем добавить и зафиксировать это как обычно; на самом деле, если вы добавляете отслеживаемый файл в gitignore, он ведет себя почти так же, как и в gitignore.
$ echo green > a.txt
$ echo blue > b.txt
$ git status --short
M a.txt
$ git add a.txt
b.txt
Файл отличается, потому что он был проигнорирован до того, как git начал его отслеживать. Этот файл обычно не попадает в репозиторий, но мы можем принудительно сделать это, если захотим.
$ git add b.txt
The following paths are ignored by one of your .gitignore files:
b.txt
Use -f if you really want to add them.
fatal: no files added
$ git add -f b.txt
Выдача git commit
теперь фиксирует два файла, которые оба были проигнорированы:
$ git commit -m '3'
2 files changed, 1 insertion(+), 1 deletion(-)
create mode 100644 b.txt
Короче говоря, подумайте о git игнорировать правила в качестве руководства:-)
Размножение предполагает - без изменений
После применения правил, предполагающих неизменность, и вызова git push, будут ли эти правила присоединены к удаленной ветви, чтобы все последующие извлечения (от других клиентов) унаследовали их? Или эти клиенты также должны запускать команды git update-index --assume-неизмененные по отдельности на своих машинах?
Последний. Самое близкое, что вы можете получить, это добавить сценарий оболочки в репозиторий, который вносит изменения за вас.
Хук сервера?
Если команды не наследуются - кто-нибудь ранее писал для этого хук сервера? Вместо того, чтобы требовать, чтобы все нынешние и будущие клиенты защитились от этого?
Если ваша цель состоит в том, чтобы написать перехват сервера, который удаляет критические файлы, как будто они вообще не были частью push, это невозможно. Git push имеет дело прежде всего с коммит- объектами (и ссылками). Их зависимые объекты, такие как деревья и объекты, передаются по мере необходимости, в зависимости от достижимости при коммите. Все сводится к тому, что, если он не зафиксирован, вы не можете отправить его на удаленный компьютер (это упрощение, но оно справедливо для файлов в хранилище). Кроме того, git коммиты криптографически защищены. Вы не можете изменить коммит, не изменив хеш коммита, и если вы измените хеш коммита, у вас в основном будет другой, новый коммит (который может иметь тот же diff, что и старый).
Это означает, что сервер не может переписать коммиты; по крайней мере, без серьезной путаницы с клиентом, который сделал push (у которого все еще будет копия старых объектов коммита).
Что вы можете сделать, это написать хук после получения, который отклоняет коммиты, если они содержат файлы, которые вы не хотите обновлять. Это на самом деле не решит вашу проблему, потому что если у вас есть проблемы с объяснением git commit --assume-unchanged
Вашим коллегам, вероятно, будет еще больше проблем с объяснением того, как они могут использовать интерактивную перебазировку для воссоздания своих коммитов без нежелательных файлов в них.
Короче говоря, я думаю, что преследовать всех за то, чтобы продолжать использовать предположения без изменений (возможно, в сочетании с ловушкой после получения) - это ваш наименее плохой выбор, если вы имеете дело с файлами, которые должны быть зафиксированы один раз, а не после, как сейчас.
Возможный обходной путь
Ваша жизнь станет намного проще, если вы сможете сохранить эти файлы от git во всей их полноте. Одна из вещей, о которых я могу думать:
- переместите файлы в хранилище в каталог lib, где они не изменяются постоянно
.gitignore
файлы в их определенном месте, где они должны быть, но постоянно получают нежелательные изменения- добавьте сценарий "init" в свой репозиторий, который люди должны запустить один раз после клонирования и перед началом работы. Этот скрипт копирует файлы в нужное место.
При работе с
npm
Как объяснялось в предыдущих ответах, невозможно размножить
git update-index --assume-unchanged
через
git
.
При этом при работе с
npm
, вы можете добавить
postinstall
хук, который обновляет индекс:
{
"scripts": {
"assume-unchanged": "git update-index --assume-unchanged file",
"postinstall": "npm run assume-unchanged"
}
}
Это будет запускаться каждый
npm install
.
Одно из возможных решений - написать хук на стороне клиента, чтобы люди не могли вносить локальные изменения в файлы, которые вы хотите игнорировать.
Эти ловушки являются скриптами, которые запускаются при определенных событиях в git, таких как pre-commit, post-commit, pre-push и т. Д. Примеры можно увидеть в <your_repo>/.git/hooks/
,
Плохая новость заключается в том, что они также не находятся под контролем версий, поэтому вы должны написать свой собственный скрипт установки, чтобы скопировать скрипт хука в .git/hooks/
,
Вот небольшой образец хука предварительной фиксации, который предотвращает forbidden.txt
файл для фиксации (его можно адаптировать для получения списка файлов):
ROOT_DIR="$(pwd)/"
LIST=$(git diff --cached --name-only --diff-filter=ACRM)
for file in $LIST
do
if [ "$file" == “forbidden.txt” ]; then
echo You cannot commit file $file. Please reset it and try again.
exit 1
fi
done
exit 0