Git: настроить пульт только для выборки?


133

Когда я запускаю 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-адреса или возможностей?


4
@sehe, нет, ты не можешь. Если URL для push-уведомлений не указан, для push-уведомлений будет использоваться URL для получения.
йойо

Ответы:


192

Я не думаю, что вы можете удалить URL-адрес 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

Вы устанавливаете URL-адрес push no-pushing, который, если в вашем рабочем каталоге нет папки с таким же именем, git не сможет ее найти. По сути, вы заставляете git использовать несуществующее местоположение.


14
Да, вы могли бы подумать, что «git remote set-url --delete --push. *» Поможет, но если вы удалите push url, то по умолчанию он вернется к URL выборки.
йойо

7
Я лично предпочитаю использовать что-то вроде « ЗАПРЕЩЕНО », более заметное. Но это дело вкуса.
Пьер-Оливье Варес

@ Pierre-OlivierVares А как насчет «DONTPUSH» ?! :)
Али Шакиба

К вашему сведению, после этого ваш файл конфигурации git должен выглядеть следующим образом: (Обратите внимание на новую опцию pushurl ) [удаленный "источник"] fetch = + refs / Heads / *: refs / remotes / origin / * url = ssh: // host / path / to / repo pushurl = ssh: // host / no-
pushing

1
Как и в случае с @ Pierre-OlivierVares, я пошел с git remote set-url --push origin -- --read-only--- обратите внимание на дополнительную --информацию, позволяющую имя с дефисами в начале. Мне это показалось более читаемым.
Lindes

13

Помимо изменения URL-адреса 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 отключен.


Отличная идея! Без более сложного сценария вы бы отключили push для всех пультов.
v01pe

1
@ v01pe да. Я обновил ответ, включив в него пример сценария. На самом деле не нужно много фильтровать нажатия на одну ветку. Подойдет и простая оболочка.
Родольфо Карвалью,

4

Общее утверждение «Git откажется отправлять данные в репозиторий, отличное от чистого», неверно. Git откажется от отправки в удаленный репозиторий, отличный от чистого, если вы попытаетесь отправить изменения, которые находятся в той же ветке, что и рабочий каталог удаленного репозитория.

Этот ответ дает простое объяснение: https://stackoverflow.com/a/2933656/1866402

(Я добавляю это как ответ, потому что у меня еще недостаточно репутации, чтобы добавлять комментарии)


чистый репозиторий по определению не имеет зарегистрированного рабочего каталога. Однако вы можете нажать на конкретную ветку на нем.
Эд Рэндалл

1

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

Дополнительная информация: git-config pushRemote


0

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


Если вы не можете изменить файлы, вы также не сможете получить новые изменения.
Просто студент
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.