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, и он будет работать просто отлично.