Git push error '[удаленный отклонен] master -> master (ветка в настоящее время извлечена)'


961

Вчера я опубликовал вопрос о том, как клонировать Git- репозиторий с одной из моих машин на другую, Как я могу «git clone» с другой машины? ,

Теперь я могу успешно клонировать Git-репозиторий из моего источника (192.168.1.2) в пункт назначения (192.168.1.1).

Но когда я сделал редактирование файла, a git commit -a -m "test"и a git push, я получаю эту ошибку в пункте назначения (192.168.1.1):

git push                                                
hap@192.168.1.2's password: 
Counting objects: 21, done.
Compressing objects: 100% (11/11), done.
Writing objects: 100% (11/11), 1010 bytes, done.
Total 11 (delta 9), reused 0 (delta 0)
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.
error: 
error: To squelch this message and still keep the default behaviour, set
error: 'receive.denyCurrentBranch' configuration variable to 'refuse'.
To git+ssh://hap@192.168.1.2/media/LINUXDATA/working
! [remote rejected] master -> master (branch is currently checked out)
error: failed to push some refs to 'git+ssh://hap@192.168.1.2/media/LINUXDATA/working'

Я использую две разные версии Git (1.7 на удаленной и 1.5 на локальной машине). Это возможная причина?


5
Может ли какой-либо старый таймер изменить принятый ответ на stackoverflow.com/a/9283833/397872 и переместить поток в архив или что-то еще? Или сменить владельца или еще что?
Ришта

9
На самом деле у вас теперь есть безопасный способ перейти к непроигрышному репо с Git 2.3.0 (февраль 2015 г.) и git config receive.denyCurrentBranch=updateInstead: stackoverflow.com/a/28262104/6309
VonC

Это новая ссылка на книгу, упомянутая @stigi
Абделила Эль Айссауи


Но я не понимаю, почему и как это работает? Это работает, да, но это все.
Тилак Мэдди

Ответы:


1149

Вы можете просто преобразовать свой удаленный репозиторий в пустой репозиторий (в пустом репозитории нет рабочей копии - папка содержит только фактические данные репозитория).

Выполните следующую команду в вашей папке удаленного хранилища:

git config --bool core.bare true

Затем удалите все файлы, кроме .gitэтой папки. И тогда вы сможете выполнить git pushв удаленном хранилище без каких-либо ошибок.


4
Спасибо. Мне тоже это было нужно. Я следовал учебнику по подмодулям из Git Community Book и преодолел этот контрольно-пропускной пункт.
Шики

6
Я не был уверен, хотите ли вы удалить файлы на сервере или на клиенте ... поэтому я ничего не удалил, и проблема исчезла после выполнения всего этого git config --bool core.bare true. Есть ли какая-то особая причина, по которой некоторые файлы нужно удалить? Если да, можете ли вы быть более точным в том, что нужно удалить?
Брайан Ванденберг

24
Это наилучший из возможных ответов, и никто больше не предоставил его в дыру Interwebs. Я думаю, что мы все погуглили одно и то же сообщение об ошибке, и мы все были очень рады прочитать это.
Себастьян Гриньоли

40
Хотя он получил много голосов, я не думаю, что это действительно адекватный ответ на этот конкретный вопрос. Инструктаж пользователя о том, как правильно создать чистое хранилище, был бы наполовину плохим, но что, если файлы должны оставаться проверенными, например, когда это хранилище, с которым работает пользователь на двух компьютерах?
Нигде человек

9
Изменение исходного репо на голое - это излишне. Все, что вам нужно сделать, это нажать на новую ветку в репо-источнике, как указывает @Robert: stackoverflow.com/a/2933656/402949 .
Дэн Соловай

708

У меня была та же ошибка, когда я начал изучать Git . Некоторые другие ответы явно не для кого-то нового в Git!

(Я собираюсь использовать нетехнические термины, чтобы донести идею.) В любом случае, у вас есть два хранилища: одно - оригинал, который вы впервые сделали, а другое - работа, которую вы только что сделали.

Прямо сейчас вы находитесь в своем рабочем репозитории и используете ветку «master». Но вы также «залогинены» в исходном репозитории в ту же «главную» ветку. Теперь, когда вы «вошли» в оригинал, Git боится, что вы можете испортить, потому что вы можете работать с оригиналом и все испортить. Так что вам нужно вернуться в исходный репозиторий и выполнить «git checkout someotherbranch», и теперь вы можете выполнить без проблем.

Надеюсь, это поможет.


76
+1 Гораздо полезнее, спасибо, Роберт. У меня не было смысла переходить на голый репо в моем случае. Просто нужно «деактивировать» ветку, на которую вы пытаетесь нажать. Имеет смысл.
Эрик Муйзер

32
@ FMaz008: просто создайте фиктивную ветку (git checkout -b dummy)
Дрор Коэн,

14
Человек это гораздо лучше, чем большинство проголосовавших ответ :) Спасибо. Хотя другой ответ также имеет смысл :)
Иван Иванич

103
Просто чтобы сделать это более ясным, в репо , что это цель нажима: git checkout -b tmp. Тогда в источнике репо: git push. Затем вернитесь в цель (необязательно):git checkout master; git branch -d tmp
Хари Карам Сингх

18
Комментарий Хари - самый простой рецепт. Я просто должен сказать, что, хотя git может быть отличным во многих отношениях, начиная с SVN или, возможно, с других rvs, все это потрясающе не интуитивно понятно.
Безусловно, Восстановить

128

Сообщение об ошибке описывает, что произошло. Более современные версии Git отказываются обновлять ветку с помощью push, если эта ветка извлечена.

Самый простой способ работать между двумя не голыми репозиториями - это либо

  1. всегда обновляйте репозитории с помощью pull (или fetch and merge) или, если нужно,

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

Причина этого ограничения заключается в том, что операция push работает только в удаленном репозитории Git, у нее нет доступа к индексу и рабочему дереву. Таким образом, если это разрешено, отправка извлеченной ветки изменит ее HEAD на несовместимую с индексом и рабочим деревом в удаленном хранилище.

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


1
Спасибо. Так как я могу исправить мою проблему? В моем окне 192 я сделал «$ cd (каталог-проект) $ git init $ (добавить несколько файлов) $ git add». и затем в своем окне 191 я сделал «git clone» и отредактировал некоторые файлы, а затем попытался «git push».
hap497

16
Ну, я описал возможности в своем ответе. Либо вы можете перейти к блоку 192 и извлечь его из блока 191 (вы можете добавить блок 191 в качестве именованного удаленного устройства - посмотрите git remote add box191 <191url>), либо вы можете перейти из блока 191 в альтернативно названную ветвь (например git push origin master:refs/heads/upload), затем в поле 192 и объединить (например git merge upload).
CB Bailey

3
Теперь у вас есть безопасный способ перейти к репозиторию без использования Git 2.3.0 (февраль 2015 г.) и git config receive.denyCurrentBranch=updateInstead: stackoverflow.com/a/28262104/6309 : вам больше не нужен вариант 2.
VonC

122

Резюме

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

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

Есть несколько решений, в зависимости от ваших потребностей.

Решение 1. Используйте голое хранилище

Как и предполагалось, если на одной машине вам не нужен рабочий каталог, вы можете перейти в пустой репозиторий. Чтобы не связываться с хранилищем, вы можете просто его клонировать:

machine1$ cd ..
machine1$ mv repo repo.old
machine1$ git clone --bare repo.old repo

Теперь вы можете отправить все, что вы хотите, на тот же адрес, что и раньше.

Решение 2. Перейдите в не проверенную ветвь

Но если вам нужно проверить код на вашем пульте <remote>, вы можете использовать специальную ветку для push. Допустим, в вашем локальном хранилище вы назвали свой удаленныйorigin и вы работаете с мастером филиала. Тогда вы могли бы сделать

machine2$ git push origin master:master+machine2

Затем вам нужно объединить его, когда вы находитесь в origin удаленном репо:

machine1$ git merge master+machine2

Вскрытие проблемы

Когда ветвь извлечена, фиксация добавит новый коммит с заголовком текущей ветки в качестве его родителя и переместит голову ветки, чтобы стать этим новым коммитом.

Так

A ← B
    ↑
[HEAD,branch1]

становится

A ← B ← C
        ↑
    [HEAD,branch1]

Но если бы кто-то мог нажать на эту промежуточную ветвь, пользователь оказался бы в том, что git называет режим отключенной головы :

A ← B ← X
    ↑   ↑
[HEAD] [branch1]

Теперь пользователь больше не находится в branch1, без явного запроса проверить другую ветку. Хуже того, пользователь теперь находится вне какой-либо ветви , и любой новый коммит будет просто зависать :

      [HEAD]
        ↓
        C
      ↙
A ← B ← X
        ↑
       [branch1]

Гипотетически, если в этот момент пользователь проверяет другую ветвь, то этот висячий коммит становится честной игрой для сборщика мусора в Git .


3
Одно техническое исправление к «вскрытию»: git на самом деле не отсоединяется HEADв репозитории push-to. HEADбудет по-прежнему указывать на ветвь, а ветка в свою очередь будет указывать на новую отправленную фиксацию; но рабочий каталог и index / staging-area будут неизменными. Тот, кто работает с репозиторием с принудительным переносом, теперь должен усердно работать, чтобы оправиться от последствий толчка: выяснить, есть ли какие-либо изменения для сохранения и, если это необходимо, тщательно подготовить их для сохранения.
torek

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

2
На самом деле, я обнаружил много ситуаций, когда мне нужно перейти в не-пустой репозиторий, и я довольно часто использую решение 2. Кроме того, ветвь, в которую я помещаю репозиторий non-bare, ни в коем случае не является временной веткой, она выполняет те же функции, что и ветка удаленного отслеживания.
Нигде человек

Я создал на своем сервере папку GIT, в которой будут размещаться ВСЕ репозитории, созданные несколькими пользователями с использованием SourceTree. Я создал masterрепозитории на своем локальном ПК. Я добавил remotesпапку в папку на сервере и пытался вставить свой репозиторий на сервер, чтобы другой пользователь мог извлечь / извлечь его для работы. Я получаю следующую ошибку: ! [remote rejected] master -> master (branch is currently checked out)Как я могу проверить это?
SearchForKnowledge

2
@SearchForKnowledge, ты понимаешь, что задаешь именно тот вопрос, на который я отвечаю ?!
Нигде человек

65

Вы можете обойти это «ограничение», отредактировав его .git/configна целевом сервере. Добавьте следующее, чтобы разрешить отправку репозитория git, даже если он «извлечен»:

[receive]
denyCurrentBranch = warn

или

[receive]
denyCurrentBranch = false

Первое позволит толкать, предупреждая о возможности испортить ветку, а второе просто спокойно это разрешит.

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


7
Использование этого для «развертывания» кода на сервере не будет работать. Даже если вы отключите предупреждение, чтобы можно было нажать на извлеченную ветку, рабочая копия НИКОГДА не обновляется при нажатии.
Arrowmaster

10
Я использую описанный выше метод с cd .. && git reset --hardхуком post-receive для развертывания. Взломать, но работает.
jholster

9
версия командной строки последнего будетgit config receive.denyCurrentBranch warn
Андре Хольцнер

4
Это должен быть принятый ответ. Некоторые из нас знают, что мы делаем, и не новички в Git. Это ответ для тех людей.
Qix - МОНИКА ПРОИЗОШЛА

2
Ха, но этот вопрос не был задан этими людьми.
Нигде человек

46

git config --local receive.denyCurrentBranch updateInstead

https://github.com/git/git/blob/v2.3.0/Documentation/config.txt#L2155

Используйте это в репозитории сервера, и оно также обновляет рабочее дерево, если не будет перезаписи без отслеживания.

Это было добавлено в Git 2.3, как упомянуто VonC в комментариях.

Я скомпилировал Git 2.3 и попробовал. Пример использования:

git init server
cd server
touch a
git add .
git commit -m 0
git config --local receive.denyCurrentBranch updateInstead

cd ..
git clone server local
cd local
touch b
git add .
git commit -m 1
git push origin master:master

cd ../server
ls

Вывод:

a
b

Yay, bтолкнул!


@VonC спасибо! Это моя одержимость минимальными примерами на работе :-)
Сиро Сантилли 郝海东 冠状 病 六四 事件 法轮功

Есть ли какие-либо проблемы с фиксацией изменений, которые не обновлены на сервере?
Акози

@akozi Я не уверен, что вы имеете в виду, если вы делаете локальный коммит перед извлечением, он будет вести себя точно так же, как традиционный --bareклон, я думаю: --forceтребуется нажать, и это заставит вас «потерять» коммиты на пульте.
Сиро Сантилли 郝海东 冠状 病 六四 事件 法轮功

1
@CiroSantilli 法轮功 改造 中心 六四 事件 法轮功 Не беспокойся. Я посмотрел значение вариантов. Я думал, что updateInstead - это синоним силы.
Акози

updateInstead больше не является допустимым значением для receive.denyCurrentBranch
Xalorous

41

Мне нравится идея о том, что на удаленном компьютере все еще можно использовать репозиторий, но вместо фиктивной ветки мне нравится использовать:

git checkout --detach

Кажется, это очень новая функция Git - я использую git версии 1.7.7.4.


8
А затем, после внесения изменений, вы можете использовать:, git checkout masterчтобы вернуться в главную ветку. Только тогда ваши изменения будут применены.
МАЗДАК

30

Я была такая же проблема. Для меня я использую Git push для перемещения кода на мои серверы. Я никогда не меняю код на стороне сервера, так что это безопасно.

В репозитории вы нажимаете, чтобы набрать:

git config receive.denyCurrentBranch ignore

Это позволит вам изменить хранилище, пока оно является рабочей копией.

После запуска Git push перейдите на удаленный компьютер и введите:

git checkout -f

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

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


спасибо журнал, я объединяю ваше предложение denyCurrentBranchи помещаю git checkout -fв hooksпапку, как @ jack-senechal, размещенный здесь
Эдерсон Т. Szlachta

Есть ли способ заставить файлы появляться в удаленном хранилище, не заходя в него и не выполняя эту команду? А именно по команде из местного?
Рой

24

Вы можете воссоздать свой репозиторий сервера и перенести его с главного локального филиала на главный сервер.

На вашем удаленном сервере:

mkdir myrepo.git
cd myrepo.git
git init --bare

ОК, из вашего местного отделения:

git push origin master:master

3
Спасибо, это было решением для меня, так как я опустил '--bare' на удаленном сервере. Похоже, что ответы на этот вопрос зависят от того, используете ли вы удаленный репозиторий в качестве рабочего каталога или нет, и для последующего случая это правильный ответ.
Cas

2
Я не понимаю: SI пытался создать и клонировать голое репо, но клон ничего не загрузил и ничего не загрузил, так что это не работает ... :-) Я читал учебники о голых репо, но они говорят, что голое репо не содержит файлов ... Это определенно не то, что я ищу ...
inf3rno

22

Что вы, вероятно, сделали, чтобы вызвать это:

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

machine1:~/proj1> git init

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

machine2:~> git clone ssh://machine1/~/proj1

и он клонируется, и все выглядит хорошо, и поэтому вы работаете над своим кодом с machine2.

затем ... вы пытаетесь отправить свои коммиты с machine2, и вы получите предупреждающее сообщение в заголовке.

Причиной этого сообщения является то, что git-репо, из которого вы извлекли, было как бы предназначено для использования только для этой папки на машине1. Вы можете клонировать его просто отлично, но нажатие может вызвать проблемы. «Правильный» способ управления кодом в двух разных местах - это «голое» репо, как было предложено. Голые репо не предназначена, что любая работа делается в ней, она призвана координировать коммиты из нескольких источников. Вот почему самый лучший ответ предлагает удалить все файлы / папки, кроме папки .git, после того, как выgit config --bool core.bare true .

Уточнение ответа с самым высоким рейтингом: во многих комментариях к этому ответу говорится что-то вроде: «Я не удалял файлы, не относящиеся к .git, с machine1, и я все еще мог зафиксировать с machine2». Вот так. Однако эти другие файлы полностью «отделены» от git-репо. Попробуйте git statusтам, и вы должны увидеть что-то вроде «роковой: эта операция должна выполняться в рабочем дереве». Таким образом, предложение удалить файлы не так, чтобы коммит с machine2 работал ; это чтобы вы не запутались и не подумали, что git все еще отслеживает эти файлы. Но удаление файлов является проблемой, если вы все еще хотите работать с файлами на компьютере1, не так ли?

Итак, что вы должны делать?

Зависит от того, сколько вы планируете по-прежнему работать на machine1 и machine2 ...

Если вы закончили разработку с machine1 и перенесли всю свою разработку на machine2 ... просто сделайте то, что предлагает ответ с самым высоким рейтингом: git config --bool core.bare trueа затем, при необходимости, удалите все файлы / папки, кроме .git, из этой папки, так как они не отслежены и могут вызвать путаницу.

Если ваша работа на machine2 была разовой, и вам не нужно продолжать там разработку ... тогда не пытайтесь делать голое репо; просто ftp / rsync / scp / и т.д. ваши файлы с машины * 2 * поверх файлов на машине * 1 *, подтвердите / нажмите с машины * 1 *, а затем удалите файлы с машины * 2 *. Другие предлагали создать ветку, но я думаю, что это немного запутанно, если вы просто хотите объединить какую-то разработку, которую вы делали единовременно, с другой машины.

Если вам нужно продолжить разработку как на machine1, так и на machine2 ... тогда вам нужно правильно все настроить. Вам нужно конвертировать репо в голое, затем вам нужно сделать клон этого на machine1, чтобы вы могли с ним работать . Вероятно, самый быстрый способ сделать это -

machine1:~/proj1> git config --bool core.bare true
machine1:~/proj1> mv .git/ ../proj1.git
machine1:~/proj1> cd ..
machine1:~> rm -rf proj1
machine1:~> git clone proj1.git
machine1:~> cd proj1

Очень важно: поскольку вы перенесли расположение репозитория с proj1 на proj1.git, вам необходимо обновить его в файле .git / config на machine2 . После этого вы можете зафиксировать свои изменения с machine2. Наконец, я стараюсь хранить свои голые репозитории в центральном месте, вдали от моих рабочих деревьев (то есть не помещайте «proj1.git» в ту же родительскую папку, что и «proj1»). Я советую вам сделать то же самое, но я хотел, чтобы описанные выше шаги были максимально простыми.


Очень подробно и полезно. Мой случай был последним, и твои инструкции сработали как шарм.
pojda

Я в случае 3, и я сделал что-то немного другое: mk git-server; mv .git git-server / proj.git и затем git clone git-server / proj.git в 1 и 2 (или git remote origin ...), используя правильный префикс ssh: // для машины 2. Таким образом Я оставлю голую мастер-копию, которая будет похожа на ту, что обычно на GH или другом HTTP-сервере, и я буду продолжать использовать push / pull на обеих машинах.
zakmck

18

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

git push production

Что приятно и просто, и вам не нужно заходить на удаленный сервер и делать попытки или что-то еще. Обратите внимание, что это будет работать лучше всего, если вы не используете свой производственный контроль как рабочую ветку! (OP работал в несколько ином контексте, и я думаю, что решение @Robert Gould хорошо сработало. Это решение больше подходит для развертывания на удаленном сервере.)

Во-первых, вам нужно настроить пустой репозиторий где-то на вашем сервере, вне вашего webroot.

mkdir mywebsite.git
cd mywebsite.git
git init --bare

Затем создайте файл hooks/post-receive:

#!/bin/sh
GIT_WORK_TREE=/path/to/webroot/of/mywebsite git checkout -f

И сделайте файл исполняемым:

chmod +x hooks/post-receive

На вашей локальной машине,

git remote add production git@myserver.com:mywebsite.git
git push production +master:refs/heads/master

Все готово! Теперь в будущем вы можете использоватьgit push production для развертывания ваших изменений!

Кредит на это решение идет в http://sebduggan.com/blog/deploy-your-website-changes-using-git/ . Ищите там более подробное объяснение того, что происходит.


Ваше предложение мне очень помогло, но я не использовал bare, я следую этому и сливаюсь с hooks(что вы предложили) и работал отлично.
Эдерсон Т. Шляхта

11

Вы должны только подтолкнуть к голому хранилищу. Пустое хранилище - это хранилище, в котором нет проверенных веток. Если вы перейдете в пустой каталог репозитория, вы увидите только содержимое каталога .git.


9
Нет ничего плохого в том, чтобы перейти к не проверенной ветке в не-пустом хранилище. Это совершенно правильный способ работы.
CB Bailey

Справедливо, это сработало бы. Но это не то, что делает пользователь.
Рибальд Эдди

13
Это не факт, что он не использует голый репозиторий, который является «неправильным»; это факт, что он подталкивает к проверенной ветке. Нет никаких доказательств того, что у него есть или он хочет иметь отдельный пустой репозиторий, поэтому ваше общее заявление о том, что он должен толкать его только в пустой репозиторий, не дает запрашивающему все варианты; один из которых мог бы легче решить его непосредственную проблему.
CB Bailey

10

У вас есть 3 варианта

  1. Потяните и нажмите еще раз:

    git pull; git push
    
  2. Нажмите в другую ветку:

    git push origin master:foo
    

    и объединить его на пульте дистанционного управления (либо gitили выдвижной запросу )

    git merge foo
    
  3. Принудительно (не рекомендуется, если вы не намеренно изменили коммиты через rebase):

    git push origin master -f
    

    Если все еще отказано, отключите denyCurrentBranch в удаленном хранилище:

    git config receive.denyCurrentBranch ignore
    

Вариант 2 у меня работает. удаленный git init локальный мастер git push origin: филиал удаленного git merge DONE
Джеки Чонг

7

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


7

Проверьте свой .git/configв целевом проекте:

$ cat .git/config 
[core]
    repositoryformatversion = 0
    filemode = true
    bare = false
    logallrefupdates = true
[receive]
    denyCurrentBranch = updateInstead

Если core. barefalse, вы можете установить его в true:

$ git config core.bare true

а затем в вашем локальном пуш к удаленному:

git push remote_repo   // suppose the destination repo is remote_repo

это будет успешно, в remote_repo вы можете проверить версию git.

$ git log -1
commit 0623b1b900ef7331b9184722a5381bbdd2d935ba
Author: aircraft < aircraft_xxx@126.com>
Date:   Thu May 17 21:54:37 2018 +0800

и теперь вы не можете использовать git в своем «рабочем пространстве»:

$ git status
fatal: This operation must be run in a work tree

Вы должны установить bare.bareобратно в ложь.

$ git config core.bare false

5

У меня была та же проблема с использованием Git для синхронизации репозиториев на моем телефоне Android и ноутбуке. Решением для меня было сделать тягу вместо толчка, как предложил @CharlesBailey.

git push origin master в Android-хранилище у меня происходит сбой с теми же сообщениями об ошибках, которые получил @ hap497 из-за толчка к несложной проверке хранилища + рабочей копии.

git pull droid masterна ноутбуке у меня работает репозиторий и рабочая копия. Конечно, нужно предварительно запустить что-то подобное git remote add droid /media/KINGSTON4GB/notes_repo/.


4

Более ранние версии Git, используемые для разрешения проталкивания в текущую извлеченную ветвь не-пустого хранилища.

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

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

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

Repo1 - будет выступать в роли сервера, а также использоваться для разработки

Repo2 - будет только для разработки

Настройте Repo1 следующим образом

Создайте ветку, чтобы поделиться работой.

git branch shared_branch

Чтобы быть в безопасности, вы также должны создать $ (REPO) .git / hooks / update, который отклоняет любые изменения чего-либо, кроме shared_branch, потому что вы не хотите, чтобы люди копались в ваших личных ветках.

repo1/.git/hooks  (GIT_DIR!)$ cat update
#!/bin/sh
refname="$1"
oldrev="$2"
newrev="$3"

if [ "${refname}" != "refs/heads/shared_branch" ]
then
   echo "You can only push changes to shared_branch, you cannot push to ${refname}"
   exit 1
fi

Теперь создайте локальный филиал в repo1, где вы будете выполнять свою реальную работу.

git checkout -b my_work --track shared_branch
Branch my_work set up to track local branch shared_branch.
Switched to a new branch 'my_work'

(возможно, для git config --global push.default upstreamтого, git pushчтобы работать)

Теперь вы можете создать repo2 с

git clone path/to/repo1 repo2 
git checkout shared_branch 

На этом этапе у вас есть и настройки repo1, и repo2 для работы с локальными ветвями, которые запускаются и извлекаются из shared_branchrepo1, не беспокоясь об этом сообщении об ошибке или не синхронизируя рабочий каталог в repo1. Какой бы нормальный рабочий процесс вы ни использовали, он должен работать.


3

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

Например, на удаленном сервере:

git branch dev
git checkout dev

На локальной установке:

git push 

На удаленном сервере:

git merge dev

2

Вот один тест, который вы можете сделать, чтобы увидеть, как работает bareсерверная часть:

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

инициализация

Создайте каталог на своем локальном компьютере и cdвставьте в него, затем выполните следующие команды:

# initialization
git init --bare server/.git
git clone server content
git clone server local
  1. Сначала вы создаете пустой serverкаталог (обратите внимание на .git в конце). Этот каталог будет служить контейнером только для ваших файлов репозитория.
  2. Затем клонируйте свой репозиторий сервера во вновь созданный contentкаталог. Это ваш каталог live / production, который будет обслуживаться вашим серверным программным обеспечением.
  3. Первые два каталога находятся на вашем сервере, третий - локальный каталог на вашей рабочей станции.

Workflow

Теперь вот основной рабочий процесс:

  1. Войдите в localкаталог, создайте несколько файлов и зафиксируйте их. Наконец, отправьте их на сервер:

    # create crazy stuff
    git commit -av
    git push origin master
    
  2. Теперь введите contentкаталог и обновите содержимое сервера:

    git pull
    
  3. Повторите 1-2. Здесь contentможет быть другой разработчик, который также может подтолкнуть к серверу, и, localкак вы можете вытащить от него.


2

Использование этого для передачи его в удаленную ветку upstream решило эту проблему для меня:

git push <remote> master:origin/master

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


1
В более общем смысле (так как это чистый эффект команды), используя git push <remote> master:newbranch. Идея состоит в том, что вы отправляете новую ветку на удаленный узел, который затем можно объединить. Таким образом вы избежите любых проблем несоответствия, упомянутых в сообщении об ошибке.
Глина

1

Мне пришлось перезапускать git --initв существующем пустом хранилище, и это создало .gitкаталог внутри пустого дерева хранилища - я понял это после ввода git statusтам. Я удалил это, и все снова было хорошо :)

(Все эти ответы великолепны, но в моем случае это было что-то совершенно другое (насколько я вижу), как описано.)


1

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

У меня была настройка веб-проекта Eclipse + EGit при обнаружении описанной ошибки. Что мне помогло, так это простое использование приложения GitHub, которое, казалось, волшебным образом решило проблему. В то время как EGit всегда отказывался от пуша, настольное приложение GitHub просто пожало плечами и подтолкнуло мои изменения. Может быть, он обрабатывает ситуацию с несколькими входами более изящно.


1

Статья, которую я нашел, которая может быть полезна другим, - это Git за 5 минут .

У меня был проект XCode под управлением версией Git, который я хотел передать в виртуальный распределенный Ethernet (VDE), который у меня есть в DC. VDE работает Centos 5.

Ни одна из статей, которые я читал о Git, не говорила о голых репозиториях. Все это звучало так просто, пока я не попробовал то, что, по моему мнению, должно быть легко, исходя из фона SVN .

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

Так:

cd /tmp (or another other directory on your system)<br/>
git clone --bare /xcode-project-directory projectname.git<br/>
scp -r projectname.git sshusername@remotehost.com:repos/<br/>

Чтобы отправить изменения из вашего проекта Xcode после фиксации в Xcode:

cd /xcode-project-directory<br/>
git push sshusername@remotehost.com:repos/projectname.git<br/>

Я уверен, что есть более плавный и изощренный способ сделать это, но как минимум это работает. Просто, чтобы все было ясно, вот некоторые пояснения: /xcode-project-directoryкаталог, в котором хранится ваш проект xcode./Users/Your_Name/Documents/Project_Name . имя проекта - это буквально название проекта, но это может быть любое название. Git не волнует, ты будешь.

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

remotehost.comэто имя вашего удаленного хоста. Вы можете так же легко использовать его IP-адрес. Просто для большей ясности я использую Gitosis на удаленном хосте с SSH-ключами, поэтому мне не нужно вводить пароли при нажатии. В статье « Хостинг Git-репозиториев, простой (и безопасный) способ» рассказывается, как все это настроить.


1

Лучший способ сделать это:

mkdir ..../remote
cd ..../remote
git clone --bare .../currentrepo/

Это приведет к клонированию хранилища, но не создаст никаких рабочих копий .../remote. Если вы посмотрите на пульт, вы увидите созданный каталог, currentrepo.gitкоторый, вероятно, вам нужен.

Затем из вашего локального репозитория Git:

git remote add remoterepo ..../remote/currentrepo.git

После внесения изменений вы можете:

git push remoterepo master

1

Я только что столкнулся с этой проблемой в Git-репозитории на Heroku .

Я не знаю, почему у Heroku есть хранилище с ненастроенным хранилищем, но в качестве обходного пути я смог сбросить настройки удаленного хранилища и перезагрузить его.

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

Для сброса:

  1. Установите инструментальный пояс Heroku (который содержит клиент командной строки), если вы этого еще не сделали.
  2. Установите плагин heroku-repo, если вы этого еще не сделали.

    heroku plugins:install https://github.com/heroku/heroku-repo.git
    
  3. Сделайте сброс, который удалит хранилище и создаст новый, пустой

    heroku repo:reset
    
  4. Нажмите на пульт Heroku, как обычно; это перезагрузит все.


Вам может понадобиться установить инструменты репозитория Heroku, чтобы это работало. Доheroku plugins:install https://github.com/heroku/heroku-repo.git
Ноа,

1

Вам нужно будет изменить файл конфигурации на удаленном сервере, как только вы создадите пустой (пустой) репозиторий, скажем

root@development:/home/git/repository/my-project# cat config 

там вы увидите

[core]
repositoryformatversion = 0
filemode = true
bare = false
logallrefupdates = true

Вы превратите это значение от ложного до истинного, и я удалил logallrefupdates = true (не уверен в его использовании!)

в

[core]
repositoryformatversion = 0
filemode = true
bare = true

Вы можете проверить следующее

$ git remote show origin
* remote origin
Fetch URL: my-portal@development:/home/XYZ/repository/XYZ
Push  URL: my-portal@development:/home/XYZ/repository/XYZ
HEAD branch: (unknown)

Эта ветка HEAD: (неизвестно) будет показана, если вы не можете нажать. Так что, если ветвь HEAD неизвестна, вы должны изменить голое значение на true, а после успешного нажатия вы можете повторно использовать

git remote show origin

и ты увидишь

 HEAD branch: master

0

Для меня рабочее решение это:

НА УДАЛЕННО:

git checkout -b some_tmp_name

НА МЕСТНОМ

git push

НА УДАЛЕННО:

git checkout master
git branch -d some_tmp_name

Но это не реальное решение, это просто обходной путь.


Это правильное решение, если у вас нет центрального хранилища.
Рик

0

На всякий случай, если кто-то найдет это полезным. Для меня это была проблема с разрешениями на git-сервере. Я проверил проект с самого начала и отправил простой файл, а затем я получил «Push rejected: Push to origin / master был отклонен»


-1

С Git два обычных (не голых) репозитория не могут напрямую перемещать / извлекать файлы назад и вперед. Должен быть промежуточный голый репозиторий. Видимо, это похоже на семейную пару, у которой есть ребенок, и пара разводится. Родители не будут разговаривать друг с другом, но они будут общаться через ребенка.

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

Итак, вот пример:

На ПК в ~ / рабочей области

git init
echo "line 1" > afile.txt
git add .
git commit -m ‘initial import’
git clone --bare . ../remote-repository.git
git remote add origin ../remote-repository.git
git push --set-upstream origin master

На ноутбуке, в ~ / workspace (не делайте git init и т. Д.)

git clone //LJZ-DELLPC/remote-repository.git/ .

// Затем делаем различные коммиты и нажимаем на них:

echo "line 2" > afile.txt
git add afile.txt
git commit -m 'added line 2'
git push    

Затем снова на ПК, в ~ / рабочей области

git pull

// Затем делаем различные коммиты и нажимаем на них:

git push

На ноутбуке git pull

и так далее..

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

lylez@LJZ-DELLPC ~
$ cd gitdir
/home/lylez/gitdir

lylez@LJZ-DELLPC ~/gitdir
$ ls

lylez@LJZ-DELLPC ~/gitdir
$ mkdir repo1

lylez@LJZ-DELLPC ~/gitdir
$ cd repo1
/home/lylez/gitdir/repo1

lylez@LJZ-DELLPC ~/gitdir/repo1
$ git init
Initialized empty Git repository in /home/lylez/gitdir/repo1/.git/

lylez@LJZ-DELLPC ~/gitdir/repo1
$ echo "line 1" > afile.txt

lylez@LJZ-DELLPC ~/gitdir/repo1
$ git add afile.txt

lylez@LJZ-DELLPC ~/gitdir/repo1
$ git commit -m 'initial import'
[master (root-commit) f407e12] initial import
 1 file changed, 1 insertion(+)
 create mode 100644 afile.txt

lylez@LJZ-DELLPC ~/gitdir/repo1
$ git clone --bar . ../repo1-bare-clone
Cloning into bare repository '../repo1-bare-clone'...
done.

lylez@LJZ-DELLPC ~/gitdir/repo1
$ git remote add origin ../repo1-bare-clone

lylez@LJZ-DELLPC ~/gitdir/repo1
$ git push --set-upstream origin master
Branch master set up to track remote branch master from origin.
Everything up-to-date

lylez@LJZ-DELLPC ~/gitdir/repo1
$ cd ..

lylez@LJZ-DELLPC ~/gitdir
$ ls
repo1  repo1-bare-clone

lylez@LJZ-DELLPC ~/gitdir
$ mkdir repo1-remote

lylez@LJZ-DELLPC ~/gitdir
$ cd repo1-remote
/home/lylez/gitdir/repo1-remote

lylez@LJZ-DELLPC ~/gitdir/repo1-remote
$ git clone ../repo1-bare-clone .
Cloning into '.'...
done.

lylez@LJZ-DELLPC ~/gitdir/repo1-remote
$ ls
afile.txt

lylez@LJZ-DELLPC ~/gitdir/repo1-remote
$ cat afile.txt
line 1

lylez@LJZ-DELLPC ~/gitdir/repo1-remote
$ echo "line 2" >> afile.txt

lylez@LJZ-DELLPC ~/gitdir/repo1-remote
$ git add afile.txt

lylez@LJZ-DELLPC ~/gitdir/repo1-remote
$ git commit -m 'added line 2'
[master 5ad31e0] added line 2
 1 file changed, 1 insertion(+)

lylez@LJZ-DELLPC ~/gitdir/repo1-remote
$ git push
Counting objects: 3, done.
Writing objects: 100% (3/3), 260 bytes | 0 bytes/s, done.
Total 3 (delta 0), reused 0 (delta 0)
To /home/lylez/gitdir/repo1-remote/../repo1-bare-clone
   f407e12..5ad31e0  master -> master

lylez@LJZ-DELLPC ~/gitdir/repo1-remote
$ cd ../repo1

lylez@LJZ-DELLPC ~/gitdir/repo1
$ ls
afile.txt

lylez@LJZ-DELLPC ~/gitdir/repo1
$ cat afile.txt
line 1

lylez@LJZ-DELLPC ~/gitdir/repo1
$ git pull
remote: Counting objects: 3, done.
remote: Total 3 (delta 0), reused 0 (delta 0)
Unpacking objects: 100% (3/3), done.
From ../repo1-bare-clone
   f407e12..5ad31e0  master     -> origin/master
Updating f407e12..5ad31e0
Fast-forward
 afile.txt | 1 +
 1 file changed, 1 insertion(+)

lylez@LJZ-DELLPC ~/gitdir/repo1
$ cat afile.txt
line 1
line 2

lylez@LJZ-DELLPC ~/gitdir/repo1
$ echo "line 3" >> afile.txt

lylez@LJZ-DELLPC ~/gitdir/repo1
$ git add afile.txt

lylez@LJZ-DELLPC ~/gitdir/repo1
$ git commit -m 'added line 3'
[master 3fa569e] added line 3
 1 file changed, 1 insertion(+)

lylez@LJZ-DELLPC ~/gitdir/repo1
$ git push
Counting objects: 3, done.
Writing objects: 100% (3/3), 265 bytes | 0 bytes/s, done.
Total 3 (delta 0), reused 0 (delta 0)
To ../repo1-bare-clone
   5ad31e0..3fa569e  master -> master

lylez@LJZ-DELLPC ~/gitdir/repo1
$ cd ../repo1-remote/

lylez@LJZ-DELLPC ~/gitdir/repo1-remote
$ ls
afile.txt

lylez@LJZ-DELLPC ~/gitdir/repo1-remote
$ cat afile.txt
line 1
line 2

lylez@LJZ-DELLPC ~/gitdir/repo1-remote
$ git pull
remote: Counting objects: 3, done.
remote: Total 3 (delta 0), reused 0 (delta 0)
Unpacking objects: 100% (3/3), done.
From /home/lylez/gitdir/repo1-remote/../repo1-bare-clone
   5ad31e0..3fa569e  master     -> origin/master
Updating 5ad31e0..3fa569e
Fast-forward
 afile.txt | 1 +
 1 file changed, 1 insertion(+)

lylez@LJZ-DELLPC ~/gitdir/repo1-remote
$ cat afile.txt
line 1
line 2
line 3

lylez@LJZ-DELLPC ~/gitdir/repo1-remote
$ git --version
git version 2.1.1

lylez@LJZ-DELLPC ~/gitdir/repo1-remote

Это пример того, что работает, и объяснение почему. Здесь нет никакой дезинформации, кроме вашего комментария.
Лайл З,

1
«С Git два обычных (не голых) репозитория не могут напрямую выдвигать / извлекать файлы назад и вперед» - за исключением того, что они могут.
Андрей C

Хорошо, опубликуйте конкретный пример вместо атаки.
Лайл Z

Или вы могли бы погуглить это? stackoverflow.com/questions/1764380/…
Эндрю С

Первый ответ в теме вашего сайта начинается с "... но, согласно git ready и официальной git wiki, вам следует только перейти к голому репо". Следующий ответ гласит: «Если вы хотите попробовать просто нажать master -> master, то команда просто: git push origin», и это просто не работает, и существует огромное количество сообщений на этот счет. Последний ответ начинается со слов: «Я бы предложил иметь на вашем сервере репозиторий с открытым исходным кодом и локальные рабочие (не пустые) репозитории». Именно это я и предложил.
Лайл Z

-3

Мое решение (используется)

  1. Оформить заказ "мастер" на удаленном сервере
  2. Работать локально на ветке "dev"
  3. Нажмите изменения для удаленного разработчика
  4. Объединить разработчика с мастером на удаленном

бинго

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