Git: Настроить удаленный только выбор?
Когда я запускаю git remote -v
в одном из моих репозиториев Git, у которых есть удаленный доступ (ы), я вижу, что каждый пульт имеет как выборки, так и push:
$ git remote -v
<remote-name> ssh://host/path/to/repo (fetch)
<remote-name> ssh://host/path/to/repo (push)
Для пультов, указывающих на разработчиков-сверстников, нет необходимости нажимать, а Git в любом случае откажется от перехода в не-голый репозиторий. Есть ли способ сконфигурировать эти пульты как "только для выборки" без push-адреса или возможностей?
Ответы
Ответ 1
Я не думаю, что вы можете удалить push-адрес, вы можете переопределить его только как URL-адрес вытягивания. Поэтому я думаю, что самое близкое, что вы получите, это примерно так:
$ git remote set-url --push origin no-pushing
$ git push
fatal: 'no-pushing' does not appear to be a git repository
fatal: The remote end hung up unexpectedly
Вы устанавливаете push-адрес в no-pushing
, который, если у вас нет папки с тем же именем в вашем рабочем каталоге, git не сможет найти. Вы по существу вынуждаете git использовать место, которое не существует.
Ответ 2
Помимо изменения push-адреса на что-то недопустимое (например, git remote set-url --push origin DISABLED
), можно также использовать хук pre-push
.
Один быстрый способ остановить git push
состоит в том, чтобы использовать символическую ссылку /usr/bin/false
:
$ ln -s /usr/bin/false .git/hooks/pre-push
$ git push
error: failed to push some refs to '...'
Использование крючка позволяет более тонко контролировать толчки, если это желательно. См. .git/hooks/pre-push.sample
для примера того, как предотвратить принудительное выполнение незавершенных коммитов.
Чтобы предотвратить нажатие на определенную ветку или ограничить нажатие на одну ветку, это в качестве примера:
$ cat .git/hooks/pre-push
#!/usr/bin/sh
# An example hook script to limit pushing to a single remote.
#
# This hook is called with the following parameters:
#
# $1 -- Name of the remote to which the push is being done
# $2 -- URL to which the push is being done
#
# If this script exits with a non-zero status nothing will be pushed.
remote="$1"
url="$2"
[[ "$remote" == "origin" ]]
Тестовое репо с несколькими пультами:
$ git remote -v
origin ../gitorigin (fetch)
origin ../gitorigin (push)
upstream ../gitupstream (fetch)
upstream ../gitupstream (push)
Разрешено нажимать на origin
:
$ git push origin
Enumerating objects: 3, done.
Counting objects: 100% (3/3), done.
Writing objects: 100% (3/3), 222 bytes | 222.00 KiB/s, done.
Total 3 (delta 0), reused 0 (delta 0)
To ../gitorigin
* [new branch] master -> master
Не допускается передача на любой другой пульт:
$ git push upstream
error: failed to push some refs to '../gitupstream'
Обратите внимание, что скрипт хука pre-push
можно изменить, чтобы, среди прочего, напечатать сообщение для stderr о том, что push-уведомление было отключено.
Ответ 3
Общая инструкция "Git откажется от нажатия на не-голый репозиторий", это не так. Git будет отказываться только от нажатия на не-голый удаленный репозиторий, если вы пытаетесь направить изменения, которые находятся в той же ветки, что и рабочий каталог удаленных репозиториев.
Этот ответ дает простое объяснение: fooobar.com/questions/5083/...
(Я добавляю это как ответ, потому что у меня недостаточно репутации для добавления комментариев)
Ответ 4
Если у вас есть контроль над репозиторием, вы можете добиться этого, используя разрешения. Пользователь, получающий репозиторий, не должен иметь права на запись в главный репозиторий.
Ответ 5
Если у вас уже есть пульт дистанционного управления, и вы просто хотите помешать себе сделать что-то вроде случайного нажатия на master
или release/production
, вы можете предотвратить это с помощью git config
.
# prevent pushing to branch: master
$ git config branch.master.pushRemote no_push
# prevent pushing to branch: release/production
$ git config branch.release/production.pushRemote no_push
Для записи, no_push
не является специальным именем. Это просто название любой несуществующей ветки. Таким образом, вы можете использовать $ git config branch.master.pushRemote create_a_pr_and_do_not_push_directly_to_master
, и он будет работать просто отлично.