Подтвердить что ты не робот

Do git update-index - неизмененные правила распространяются на клиентов при нажатии?

Есть случаи, когда я не могу использовать файл .gitignore, иначе, на git push, критические файлы удаляются с пульта. В этих случаях я применяю git update-index --assume-unchanged <file> к файлам, которые я хочу игнорировать.

После применения правил без изменений и вызова git push, будут ли эти правила прикреплены к удаленной ветке так, чтобы все последующие тяги (от других клиентов) наследовали их? Или, должны ли эти клиенты также запускать команды git update-index --assume-unchanged <file> индивидуально на своих машинах?

Если команды не унаследованы - кто-нибудь написал серверный крюк для этого раньше? Вместо того, чтобы требовать от всех текущих и будущих клиентов защиты от этого?

4b9b3361

Ответ 1

Индекс локален для вашей рабочей станции, любые сделанные вами изменения не распространяются на другие клоны одного и того же пульта.

(обновлено, после того, как вопрос обновлен)

Файл .gitignore

Есть случаи, когда я не могу использовать файл .gitignore, иначе, при нажатии git, критические файлы удаляются с удаленного.

Это неверно. Файл 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 проигнорированы:

$ git commit -m '3'
 2 files changed, 1 insertion(+), 1 deletion(-)
 create mode 100644 b.txt

Короче говоря, подумайте о git правилах игнорирования в качестве рекомендаций: -)

Распространение предположительно без изменений

После применения правил без изменений и вызова git, будут ли эти правила прикреплены к удаленной ветки, чтобы все последующие вытаскивания (от других клиентов) наследовали их? Или, должны ли эти клиенты также запускать команды git update-index -assume-unchanged отдельно на своих машинах?

Последний. Ближе всего вы можете добавить оболочку script в репозиторий, который внесет изменения для вас.

Ключ сервера?

Если команды не унаследованы - кто-нибудь написал серверный крюк для этого раньше? Вместо того, чтобы требовать от всех текущих и будущих клиентов защиты от этого?

Если ваша цель - написать крюк сервера, который удаляет критические файлы, как если бы они не были частью нажатия, это невозможно. git push заключает в основном фиксация objectsрефов). Их зависимые объекты, такие как деревья и капли, передаются по мере необходимости, при условии достижимости от фиксации. То, к чему это сводится, заключается в том, что если оно не было выполнено, вы не можете направить его на удаленный (что упрощает, но оно верно для файлов в репозитории). Кроме того, git совершает криптографическую защиту. Вы не можете изменить фиксацию без изменения хэша фиксации, и если вы измените хеш фиксации, у вас в основном есть другой новый фиксатор (который может иметь тот же самый разницу, что и старый).

Это означает, что сервер не может переписать фиксации; по крайней мере, не без серьезного путаницы с клиентом, который сделал push (который все равно будет иметь копию старых объектов фиксации).

То, что вы можете сделать, это написать крюк post-receive, который отказывается от коммитов, если они содержат файлы, которые вы не хотите обновлять. Это действительно не решает вашу проблему, потому что, если у вас возникли проблемы с объяснением git commit --assume-unchanged вашим коллегам, у вас, скорее всего, возникнет еще больше проблем, объясняя, как они могут использовать интерактивную rebase для воссоздания своих коммитов без нежелательных файлов в них.

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

Возможная обходная работа

Ваша жизнь станет целой намного проще, если вы сможете полностью сохранить эти файлы из git. Одна из вещей, о которых я могу думать:

  • перемещать файлы в репозитории в каталог lib, где они не изменяются все время
  • .gitignore файлы в их окончательном местоположении, то, где они должны быть, но все время получать нежелательные изменения
  • добавьте "init" script в ваш репозиторий, чтобы люди запускались один раз после клонирования и перед началом работы. Этот script копирует файлы в нужное место.

Ответ 2

Одно из возможных решений заключается в написании клика на стороне клиента, чтобы люди не могли локально изменять файлы, которые вы хотите игнорировать.

Эти крючки - это скрипты, которые запускаются на определенных событиях в git, например, pre-commit, post-commit, pre-push и т.д. Вы можете увидеть образцы в <your_repo>/.git/hooks/.

Плохая новость заключается в том, что они также не находятся под управлением версиями, поэтому вам нужно написать собственную настройку script, чтобы скопировать hook script на .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