Jak wypchnąć do nie-nagiego repozytorium Git?

150

Zwykle pracuję na zdalnym serwerze przez ssh (screen i vim), gdzie mam repozytorium Git. Czasami nie jestem online, więc mam osobne repozytorium (sklonowane z mojego pilota) na moim laptopie.

Jednak nie mogę wyciągnąć z tego repozytorium po stronie zdalnej, ponieważ zwykle jestem za zaporą ogniową lub nie mam publicznego adresu IP.

Czytałem, że powinienem przesłać tylko do czystego repozytorium. W jaki sposób powinienem następnie przesłać zmiany do mojego zdalnego repozytorium?

woky
źródło
3
mieć 2 zdalne repozytoria, gołe i normalne, i używać haków. wydaje się kłopotliwe, ale zgodnie z git ready i oficjalną wiki git , powinieneś przesyłać tylko do samego repozytorium . prawdopodobnie dlatego większość hostów repozytoriów git (np. GitHub, Bitbucket) zawiera punkty zaczepienia po odbiorze, dzięki czemu możesz POST na adres URL na serwerze, który uruchamia na przykład skrypt, który wykonuje git pull github master.
Jake Berger

Odpowiedzi:

137

receive.denyCurrentBranch updateInstead

Ta opcja została dodana w Git 2.3 i sprawia, że ​​serwer aktualizuje swoje drzewo robocze, jeśli jest czyste.

Więc jeśli upewnisz się, że zawsze zatwierdzasz, zanim ściągniesz lokalnie, i utrzymujesz czyste drzewo robocze na serwerze (co powinieneś zrobić, aby uniknąć konfliktów scalania), ta opcja jest dobrym rozwiązaniem.

Przykładowe użycie:

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

Wynik:

a
b
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
źródło
czy można pushować bez tworzenia nagiego repozytorium, tak jak robi to
Heroku
2
@ANinJa Nie rozumiem, czy to nie jest dokładnie to, co robi mój przykład?
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
jest --localopcjonalne?
Yukulélé
@ Yukulélé --localwpływa tylko na bieżący katalog, --globalwpływa na wszystkie repozytoria git z ~/.gitconfig, zobacz man git-config.
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功
1
dziękuję @CiroSantilli 新疆 改造 中心 六四 事件 法轮功 po przeczytaniu dokumentu potwierdzam, że nie jest to konieczne "(możesz powiedzieć - lokalne, ale tak jest domyślnie)"
Yukulélé
146

Najlepsza opcja

Prawdopodobnie najczystszym, najmniej zagmatwanym i najbezpieczniejszym sposobem umieszczenia w zdalnym repozytorium, które nie jest puste, jest wysłanie do dedykowanych gałęzi w pilocie, które reprezentują gałęzie twojego laptopa.

Spójrzmy na najprostszy przypadek i załóżmy, że masz tylko jedną gałąź w każdym repozytorium: master. Kiedy pchasz do zdalnego repozytorium z laptopa, zamiast pchać master -> master, push master -> laptop-master (lub podobną nazwę). W ten sposób wypychanie nie wpływa na aktualnie wyewidencjonowaną gałąź główną w zdalnym repozytorium. Aby to zrobić z laptopa, polecenie jest dość proste:

git push origin master:laptop-master

Oznacza to, że lokalna gałąź główna zostanie przeniesiona do gałęzi o nazwie „laptop-master” w zdalnym repozytorium. W swoim zdalnym repozytorium będziesz mieć nową gałąź o nazwie „laptop-master”, którą możesz następnie połączyć ze zdalnym serwerem głównym, gdy będziesz gotowy.

Alternatywna opcja

Możliwe jest również po prostu push master -> master, ale wypychanie do aktualnie wyewidencjonowanej gałęzi nie-bare repo nie jest generalnie zalecane, ponieważ może być mylące, jeśli nie rozumiesz, co się dzieje. Dzieje się tak, ponieważ wypchnięcie do wyewidencjonowanej gałęzi nie aktualizuje drzewa roboczego, więc sprawdzenie git statuswyewidencjonowanej gałęzi, do której została wypchnięta, pokaże dokładnie przeciwne różnice, niż to, co zostało wysłane ostatnio. Byłoby to szczególnie mylące, gdyby drzewo robocze było brudne przed wykonaniem wypychania, co jest głównym powodem, dla którego nie jest to zalecane.

Jeśli chcesz spróbować po prostu wcisnąć master -> master, to polecenie jest po prostu:

git push origin

Ale kiedy wrócisz do zdalnego repozytorium, najprawdopodobniej będziesz chciał git reset --hard HEADzsynchronizować drzewo robocze z przekazaną zawartością. Może to być niebezpieczne , ponieważ jeśli w drzewie pracy zdalnej są jakieś niezatwierdzone zmiany, które chcesz zachować, zostaną one wymazane. Upewnij się, że wiesz, jakie są tego konsekwencje, zanim spróbujesz, lub przynajmniej najpierw wykonaj kopię zapasową!

EDYCJA Od wersji Git 2.3 możesz użyć funkcji „push-to-deploy” git push: https://github.com/blog/1957-git-2-3-has-been-released . Ale wypychanie do oddzielnej gałęzi, a następnie scalanie jest zwykle lepsze, ponieważ wykonuje faktyczne scalanie (dlatego działa z niezatwierdzonymi zmianami, tak jak robi to merge).

Dan Moulding
źródło
1
Czy można zautomatyzować rozgałęzianie po wypchnięciu laptopa-mastera?
rdoubleui
3
@rdoubleui: Czy chodziło Ci o „zautomatyzuj scalanie ”? Jeśli tak, nie, nie można zautomatyzować scalania, ponieważ nie ma gwarancji, że połączenia będą możliwe bez interwencji człowieka. Mogą wystąpić konflikty, które należy rozwiązać.
Dan Molding
7
w późniejszych wersjach (?), git config receive.denyCurrentBranch ignorenależy to zrobić przed
przejściem
3
Świetna odpowiedź @DanMoulding, dzięki. @rdoubleui: zawsze możesz zapisać wiersz poleceń, taki jak poniższy, jako funkcję bash:git push origin master:laptop-master && ssh user@remotemachine 'cd repos_path && git merge laptop-master'
Rich
@rdoubleui Aby zautomatyzować scalanie, możesz użyć gitolite i ustawić go (nieco skomplikowane), aby uczynić wszystko, co nie-bare commit, brudne i wypchnąć to do wersji gitolite (bare) używając wyzwalacza pre-git. Po tym, jeśli scalanie nie może zostać rozwiązane w trybie non-bare, odrzuci twój push, więc wiesz, że musisz najpierw wyciągnąć, rozwiązać połączenia i ponownie push. Jeszcze tego nie skonfigurowałem, ale jestem w trakcie i myślę, że to może zadziałać.
17

Sugerowałbym posiadanie czystego repozytorium i lokalnego działającego repozytorium (non-bare) na serwerze. Możesz przesłać zmiany z laptopa do samego repozytorium serwera, a następnie przeciągnąć z tego samego repozytorium do działającego repozytorium serwera. Powodem, dla którego to mówię, jest to, że możesz mieć wiele kompletnych / niekompletnych gałęzi na serwerze, które będziesz chciał replikować na laptopie.

W ten sposób nie musisz martwić się o stan gałęzi wyewidencjonowanej na serwerze działającym repozytorium podczas wypychania zmian na serwer.

Manish
źródło
4

Inną opcją jest skonfigurowanie odwróconego tunelu SSH, aby można było ciągnąć zamiast pchać.

# 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

A jeśli chcesz, aby tunel działał w tle

$ ssh -fNnR 1234:localhost:22 user@remote
Todd Freed
źródło
1

Możesz to zrobić:

$git config --bool core.bare true

można to zrobić w czystym lub centralnym repozytorium, tak aby akceptował wszystkie pliki, które są wypychane z innych niż gołe repozytoria. Jeśli zrobisz to w repozytorium non bare, nie możemy przesłać żadnych plików z repozytorium non bare do repository.

Jeśli ćwiczysz GIT, tworząc centralne i nieosłonięte repozytorium na komputerze PC, może nie wyświetlać przesłanych plików na niektórych komputerach, ale zostały one przekazane. możesz to sprawdzić, uruchamiając.

$git log w centralnym repozytorium.

Inaczej niż w przypadku push do GitHub, pokaże tam pliki.

vidwan reddy
źródło