Каковы последствия использования receive.denyCurrentBranch в Git?
У меня есть хранилище Git. Я клонировал репозиторий и могу зафиксировать свои локальные изменения. Когда я отправляю свои изменения на сервер, это работает.
Как только я создаю ветку, я извлекаю ветку, фиксирую свою работу и затем извлекаю основную ветку. Затем я объединяю свои локальные изменения в основную ветку. Когда я пытаюсь нажать на сервер, я получаю следующее исключение:
Welcome to Git (version 1.7.11-preview20120620)
Run 'git help git' to display the help index.
Run 'git help <command>' to display help for specific commands.
$ git push origin master:master
Counting objects: 9, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (7/7), done.
Writing objects: 100% (8/8), 13.68 KiB, done.
Total 8 (delta 2), reused 1 (delta 0)
Unpacking objects: 100% (8/8), done.
remote: error: refusing to update checked out branch: refs/heads/master
remote: error: By default, updating the current branch in a non-bare repository
remote: error: is denied, because it will make the index and work tree inconsistent
remote: error: with what you pushed, and will require 'git reset --hard' to match
remote: error: the work tree to HEAD.
remote: error:
remote: error: You can set 'receive.denyCurrentBranch' configuration variable to
remote: error: 'ignore' or 'warn' in the remote repository to allow pushing into
remote: error: its current branch; however, this is not recommended unless you
remote: error: arranged to update its work tree to match what you pushed in some
remote: error: other way.
remote: error:
remote: error: To squelch this message and still keep the default behaviour, set
remote: error: 'receive.denyCurrentBranch' configuration variable to 'refuse'.
To c:/jGit
! [remote rejected] master -> master (branch is currently checked out)
error: failed to push some refs to 'c:/gitRepository'
Одним из решений является выполнение следующей команды:
git config receive.denyCurrentBranch ignore
После этого это работает, но я хотел бы знать, почему мне нужно использовать эту опцию. Это единственный вариант? Каковы последствия этого?
Что я действительно хотел бы сделать, так это создать ветви, объединить их с основной веткой и затем отправить свои изменения на сервер.
6 ответов
Сервер, на который вы продвигаетесь, должен использовать пустой репозиторий.
Почему Git не позволит вам перейти в не голые репозитории
Оригинальный плакат гласит:
Одним из решений является выполнение следующей команды:
git config receive.denyCurrentBranch ignore
После этого это работает, но я хотел бы знать, почему мне нужно использовать эту опцию. Это единственный вариант? Каковы последствия этого?
Как я отмечаю в своем ответе на аналогичный вопрос, начиная с Git версии 1.6.2, Git по умолчанию не позволяет вам перемещаться в не-пустой репозиторий. Это потому что git push
Команда только обновляет ветку и HEAD
ссылки на удаленный репозиторий. Чего он не делает, так это обновляет рабочую копию и промежуточную область в этом не обнаженном пульте.
Как следствие, когда вы используете git status
в удаленном репо вы увидите, что предыдущее состояние репо все еще присутствует в рабочей копии (и находится в индексе):
$ git status
On branch master
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
new file: previous-state.txt
Если вы посмотрите на сообщение об ошибке, которое вы получили, когда впервые попытались отправить на удаленное репо без обнажения receive.denyCurrentBranch
настройка по умолчанию refuse
значение, вы увидите, что сообщение говорит вам в основном то же самое:
error: refusing to update checked out branch: refs/heads/master
error: By default, updating the current branch in a non-bare repository
error: is denied, because it will make the index and work tree inconsistent
error: with what you pushed, and will require 'git reset --hard' to match
error: the work tree to HEAD.
error:
error: You can set 'receive.denyCurrentBranch' configuration variable to
error: 'ignore' or 'warn' in the remote repository to allow pushing into
error: its current branch; however, this is not recommended unless you
error: arranged to update its work tree to match what you pushed in some
error: other way.
Вы действительно должны просто нажать на репозитории Git
Как указывалось в некоторых других ответах, вы не должны толкаться в не-пустой репозиторий, по причинам, которые я указал выше, и о которых говорит вам сам Git.
Так что, как говорится в этом ответе, простой способ преобразовать существующее непокрытое репо в простое - просто отменить его как голое репо:
git clone --bare old-repo
Или вы можете попробовать возиться с core.bare
Настройка конфигурации, как подробно описано в этом ответе.
У меня была та же ошибка, и мне нужно было, чтобы хранилище работало как тестовая страница разработчика онлайн (то есть, я думаю, чтобы хранилище не было пустым). Надеюсь, я решил это, запустив репозиторий с помощью этой серии команд (начиная с git 2.3):
git init
git config --global user.email "your@mail.here"
git config --global user.name "Your Name"
git commit
git config receive.denyCurrentBranch updateInstead
Как видно здесь: не может запихнуть в git репозиторий
У вас должен быть пустой репозиторий на сервере, а не с извлеченным рабочим деревом. Git сообщает вам, что отказывается перезаписывать ветку, которая в данный момент проверена на сервере.
Посмотрите этот ответ для получения информации о том, как преобразовать ваш не-пустой репозиторий на сервере в пустой.
Вскрытие проблемы
Когда ветвь извлечена, фиксация добавит новый коммит с заголовком текущей ветки в качестве его родителя и переместит голову ветки в этот новый коммит.
Так
A ← B
↑
[HEAD,branch1]
становится
A ← B ← C
↑
[HEAD,branch1]
Но если бы кто-то мог нажать на эту промежуточную ветвь, пользователь оказался бы в том, что git называет режимом отключенной головы:
A ← B ← X
↑ ↑
[HEAD] [branch1]
Теперь пользователь больше не находится в branch1, без явного запроса проверить другую ветку. Хуже того, пользователь теперь находится вне какой-либо ветви, и любой новый коммит будет просто зависать:
[HEAD]
↓
C
↙
A ← B ← X
↑
[branch1]
Гипотетически, если в этот момент пользователь проверяет другую ветвь, то этот висячий коммит становится честной игрой для сборщика мусора в Git.
Я думаю, что не пустой репозиторий может быть полезен, когда человек настраивает ловушку обновления git для развертывания из самого репозитория после того, как произошла загрузка. Только не забудьте сбросить репозиторий. Если вы пропустите этот шаг, файлы не будут отслеживать фактическое состояние...