Как перенести в не-голое хранилище Git?

150

Я обычно работаю на удаленном сервере через ssh (screen и vim), где у меня есть Git-репозиторий. Иногда я не в сети, поэтому у меня есть отдельный репозиторий (клонированный с моего пульта) на моем ноутбуке.

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

Я читал, что я должен нажать только на пустой репозиторий. Как мне затем отправить свои изменения в мой удаленный репозиторий?

woky
источник
связанные: stackoverflow.com/questions/12265729/…
prusswan
3
иметь 2 удаленных репо, голое и нормальное, и использовать хуки. кажется хлопотным, но, согласно git ready и официальной git wiki , вам нужно только перейти к голому репо . Вероятно, именно поэтому большинство хостов git-репо (например, GitHub, Bitbucket) включают в себя перехваты после получения, так что вы можете отправить POST по URL на вашем сервере, который запускает скрипт, который выполняется, например git pull github master.
Джейк Бергер

Ответы:

137

receive.denyCurrentBranch updateInstead

Эта опция была добавлена в 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
Сиро Сантилли 郝海东 冠状 病 六四 事件 法轮功
источник
можно ли продвигаться без создания голого репо, как это делает
heroku
2
@ANinJa Я не понимаю, разве это не то, что делает мой пример?
Сиро Сантилли 郝海东 冠状 病 六四 事件 法轮功
является --localнеобязательным?
Yukulélé
@ Yukulélé --localвлияет только на текущий каталог, --globalвлияет на все репозитории git ~/.gitconfig, см man git-config.
Сиро Сантилли 郝海东 冠状 病 六四 事件 法轮功
1
спасибо @CiroSantilli 新疆 改造 中心 六四 事件 法轮功 после прочтения документа я подтверждаю, что в этом нет необходимости "(можно сказать --local, но это по умолчанию)"
Yukulélé
146

Лучший вариант

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

Давайте рассмотрим простейший случай и предположим, что в каждом репо есть только одна ветвь: master. Когда вы нажимаете на удаленное репо с вашего ноутбука, вместо нажатия master -> master, push master -> laptop-master (или аналогичное имя). Таким образом, push не влияет на текущую извлеченную главную ветку в удаленном репо. Чтобы сделать это с ноутбука, команда довольно проста:

git push origin master:laptop-master

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

Альтернативный вариант

Также возможно просто нажать master -> master, но обычно не рекомендуется отправка в текущую извлеченную ветвь непроигранного репо, потому что это может сбить с толку, если вы не понимаете, что происходит. Это связано с тем, что отправка в извлеченную ветвь не обновляет рабочее дерево, поэтому проверка git statusв извлеченной ветке, в которую была вставлена, покажет в точности противоположные отличия от того, что было добавлено совсем недавно. Было бы особенно запутанно, если бы дерево работ было грязным до того, как был сделан пуш, что является большой причиной, почему это не рекомендуется.

Если вы хотите попробовать нажать master -> master, то команда будет просто:

git push origin

Но когда вы вернетесь к удаленному репо, вам, скорее всего, понадобится выполнить git reset --hard HEADсинхронизацию рабочего дерева с загруженным контентом. Это может быть опасно , потому что, если в удаленном рабочем дереве есть какие-то незафиксированные изменения, которые вы хотели бы сохранить, оно уничтожит их. Убедитесь, что вы знаете, каковы последствия этого, прежде чем попробовать, или, по крайней мере, сначала сделайте резервную копию!

РЕДАКТИРОВАНИЕ Начиная с Git 2.3, вы можете использовать «push-to-deploy» git push: https://github.com/blog/1957-git-2-3-has-been-released . Но лучше перейти к отдельной ветви, а затем к слиянию, поскольку оно выполняет фактическое слияние (следовательно, работает с незафиксированными изменениями, как слияние).

Дэн Молдинг
источник
1
Можно ли автоматизировать разветвление после нажатия на ноутбук-мастер?
rdoubleui
3
@rdoubleui: Вы имели в виду «автоматизировать слияние »? Если это так, то нет, автоматизировать слияние невозможно, поскольку слияние не гарантируется без вмешательства человека. Могут быть конфликты, с которыми нужно разобраться.
Дэн Молдинг
7
в более поздних версиях (?), git config receive.denyCurrentBranch ignoreэто должно быть сделано до того, как вы
перейдете к репозиториям
3
Отличный ответ @DanMoulding, спасибо. @rdoubleui: вы всегда можете сохранить командную строку, например, как функцию bash:git push origin master:laptop-master && ssh user@remotemachine 'cd repos_path && git merge laptop-master'
Rich
@rdoubleui, чтобы автоматизировать слияние, вы можете использовать gitolite и настроить его (немного сложно), чтобы не-голый фиксировал все грязное и помещал его в версию gitolite (голую), используя триггер pre-git. После этого, если слияние не может быть разрешено в не-голом, оно отклонит ваш толчок, так что вы знаете, что вам нужно сначала потянуть, разрешить слияния и снова нажать. Я еще не настроил это, но я нахожусь в процессе и думаю, что это может работать.
17

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

Таким образом, вам не нужно беспокоиться о состоянии ветки, проверенной на рабочем репо сервера, при отправке изменений на сервер.

Manish
источник
4

Другой вариант - настроить обратный ssh-туннель, чтобы вы могли тянуть вместо push.

# start the tunnel from the natted box you wish to pull from (local)
$ ssh -R 1234:localhost:22 user@remote

# on the other box (remote)
$ git remote add other-side ssh://user@localhost:1234/the/repo
$ git pull other-side

И если вы хотите, чтобы туннель работал в фоновом режиме

$ ssh -fNnR 1234:localhost:22 user@remote
Тодд Фрид
источник
1

Ты можешь сделать:

$git config --bool core.bare true

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

Если вы практикуете GIT, создавая центральное и не обнаженное репо на ПК, он может не показывать загруженные файлы на некоторых ПК, но он был перенесен. Вы можете проверить это, запустив.

$git log в центральном репо.

Если вы не нажмете на GitHub, он покажет файлы там.

Видван Редди
источник