2016-09-26 7 views
8

Mam repozytorium git ze zdalnym origin dublowane na 3 hosty.Git: - force-with-lease i wiele pushurls

$ git remote -v 
origin [email protected]:username/repo.git (fetch) 
origin [email protected]:username/repo.git (push) 
origin [email protected]:username/repo.git (push) 
origin [email protected]:username/repo.git (push) 

Wszystko, wszędzie jest popełnić .

$ git rev-parse HEAD 
A 

$ cat .git/refs/remotes/origin/master 
A 

I autor popełnić B i przesunąć go. Teraz wszyscy są zatwierdzeni B.

$ git push origin master 
To github.com:username/repo.git 
    A...B    master -> master 
To gitlab.com:username/repo.git 
    A...B    master -> master 
To bitbucket.org:username/repo.git 
    A...B    master -> master 

$ git rev-parse HEAD 
B 

$ cat .git/refs/remotes/origin/master 
B 

Teraz zauważam błąd w tym ostatnim zatwierdzeniu, więc naprawiam go i ammend commit. To sprawia, że ​​nie jestem zsynchronizowany z pilotem (ami).

$ git rev-parse HEAD 
C 

$ cat .git/refs/remotes/origin/master 
B 

chciałbym uniknąć ślepo --force popychanie, więc używam --force-with-lease, ale to się nie powiedzie w ciekawy sposób.

$ git push --force-with-lease origin master 
To github.com:username/repo.git 
+ B...C    master -> master (forced update) 
To gitlab.com:username/repo.git 
! [rejected]  master -> master (stale info) 
To bitbucket.org:username/repo.git 
! [rejected]  master -> master (stale info) 

Problem polega na tym, --force-with-lease będzie brać pod uwagę tylko jeśli push bezpieczny zdalny sędzią jest przy tym popełnić jak ostatnim razem I przekazywane z niego, a moje lokalne rekordy SHA1 tego popełnić w .git/refs/remotes/origin/master. Gdy tylko zostanie zaktualizowane pierwsze lustro (GitHub), git aktualizuje zdalny lokalny plik referencyjny GitHub, aby zatwierdzić C, powodując, że próby wypychania GitLab i Bitbucket zakończyły się niepowodzeniem, ponieważ oczekujemy teraz, że będą one zatwierdzane jako C.

Chcę to zrozumieć, więc najpierw zmuszam lustro GitHub do zatwierdzenia B.

$ git push origin +B:refs/heads/master 
To github.com:username/repo.git 
+ C...B    B -> master (forced update) 
Everything up-to-date 
Everything up-to-date 

Teraz muszę być bardziej szczegółowy o tym, którego zatwierdzenia oczekuję od pilotów. Dokumentacja mówi, że możesz dokładnie określić, które odnowienie chcesz zaktualizować, i jakiego zatwierdzenia oczekujesz obecnie z --force-with-lease=<refname>:<expect>, więc próbuję tego.

$ git push --force-with-lease=origin/master:B origin master 
To github.com:username/repo.git 
! [rejected]  master -> master (non-fast-forward) 
To gitlab.com:username/repo.git 
! [rejected]  master -> master (non-fast-forward) 
To bitbucket.org:username/repo.git 
! [rejected]  master -> master (non-fast-forward) 

Najwyraźniej robię coś nie tak. Może mam niewłaściwy kod <refname>? Czuję, że jestem tak blisko. czego mi brakuje?

+0

Interesujący test do wypróbowania: 'git push --force-with-lease = $ (git rev-parse origin/master): B origin master' (tzn. Surowy identyfikator zatwierdzenia zamiast nazwy). Nie jestem pewien, kiedy Git zmienia nazwę na tłumaczenie ID dla tego konkretnego przypadku krawędzi. – torek

+0

@torek To było warte strzału, ale bez kości. Zrobiło to samo (wszystkie wypychania odrzucone jako "non-fast-forward"). – ivan

+1

Interesujące. Po prostu zgaduję (kod jest dość kręty), ale podejrzewam, że opcja force-with-lease zapominała gdzieś podczas wielu adresów URL. Założę się, że działa znacznie lepiej, jeśli masz tylko jeden pilot dla każdego adresu URL. – torek

Odpowiedz

3

Bardzo interesujące pytanie! Próbowałem go i pomyślnie odtworzone co opisujesz z Git 2.11.0 w tych repo testowych:

udało mi się wcisnąć z powodzeniem zarówno --force-with-lease zdalne adresy URL za pomocą poniższego formularza:

git push --force-with-lease origin +master 

zauważy znak + przed oddziału na mnie.Oto wynik:

$ git push --force-with-lease origin +master 
Counting objects: 2, done. 
Delta compression using up to 4 threads. 
Compressing objects: 100% (2/2), done. 
Writing objects: 100% (2/2), 232 bytes | 0 bytes/s, done. 
Total 2 (delta 0), reused 0 (delta 0) 
To github.com:hkdobrev/git-test.git 
+ 099b95f...08c7548 master -> master (forced update) 
Counting objects: 2, done. 
Delta compression using up to 4 threads. 
Compressing objects: 100% (2/2), done. 
Writing objects: 100% (2/2), 232 bytes | 0 bytes/s, done. 
Total 2 (delta 0), reused 0 (delta 0) 
To github.com:hkdobrev/git-test2.git 
+ 099b95f...08c7548 master -> master (forced update) 

Od strony git-push (1) Man:

Zauważ, że --force dotyczy wszystkich pozycjach piśmiennictwa, które są wypychane, a więc używając go z push.default zestawu do dopasowania lub z wielu miejsc do pchania skonfigurowane za pomocą remote.*.push mogą nadpisywać wartości odniesienia inne niż bieżąca gałąź (w tym lokalne wartości odniesienia ściśle związane z ich odległym odpowiednikiem ). Aby wymusić wypychanie tylko do jednej gałęzi, należy użyć przedrostka o numerze +, aby przepchnąć (np. git push origin +master, aby wymusić wypychanie do gałęzi master ). Zobacz sekcję <refspec>... powyżej, aby uzyskać szczegółowe informacje.

+0

Interesujące! To naprawdę działa. – ivan