Jak zarządzać konfliktami z modułami podrzędnymi Git?

127

Mam superprojekt git, który odwołuje się do kilku podmodułów i próbuję zablokować przepływ pracy, aby reszta członków mojego projektu mogła pracować.

W przypadku tego pytania powiedzmy, że wywoływany jest mój superprojekt superyi podmoduł subby. (Dalej jest uproszczenie tego, co próbuję zrobić ... Właściwie nie używam gałęzi do wersji, ale pomyślałem, że najłatwiej będzie to ułożyć jako pytanie.)

Moja główna gałąź superyma znacznik v1.0projektu git, do którego subbyodwołuje się moduł podrzędny. Oddział superyo nazwie one.onei zmienił nazwę z modułem do punktu do znacznika v1.1z subby.

Mogę bez problemu pracować w każdej z tych gałęzi, ale jeśli spróbuję zaktualizować one.onegałąź o zmiany zmaster gałęzi, pojawiają się konflikty i nie wiem, jak je rozwiązać.

Zasadniczo po uruchomieniu git pull . masterw subbygałęzi wygląda na to, że tworzy dodatkowe podmoduły.

Przed łóżkiem / scalania, uzyskać pożądaną odpowiedź git submodulez one.onebranży:

$ git checkout master
$ git submodule
qw3rty...321e subby (v1.0)
$ git checkout one.one
$ git submodule
asdfgh...456d subby (v1.1)

Ale po ściągnięciu dodaje dodatkowe podmoduły, gdy uruchamiam git submodule:

$ git pull . master
Auto-merged schema
CONFLICT (submodule): Merge conflict in subby - needs qu3rty...321e
Automatic merge failed; fix conflicts and then commit the results.

$ git submodule
qw3rty...321e subby (v1.0)
asdfgh...456d subby (v1.1)
zxcvbn...7890 subby (v1.1~1)

Jak usunąć / zignorować niechciane odniesienia do podmodułów i zatwierdzić moje konflikty i zmiany? A może istnieje parametr, którego mogę użyć z oryginałem git pull, który ignoruje moje moduły podrzędne?

Tyler
źródło

Odpowiedzi:

23

Nie widziałem wcześniej tego dokładnego błędu. Ale mam przypuszczenie, jakie problemy napotykasz. Wygląda na to, że gałęzie masteri zawierają różne referencje dla podmodułu, podczas scalania zmian z git nie wie, który ref - lub - powinien być przechowywany i śledzony przez gałąź .one.onesuperysubbymasterv1.0v1.1one.onesupery

W takim przypadku musisz wybrać żądany odnośnik i zatwierdzić tę zmianę, aby rozwiązać konflikt. Dokładnie to robisz za pomocą polecenia resetowania .

Jest to trudny aspekt śledzenia różnych wersji modułu podrzędnego w różnych gałęziach projektu. Ale ref podmodułu jest jak każdy inny komponent twojego projektu. Jeśli dwie różne gałęzie nadal śledzą te same odnośniki podmodułów po kolejnych połączeniach, to git powinien być w stanie wypracować wzór bez wywoływania konfliktów łączenia w przyszłych połączeniach. Z drugiej strony, jeśli często przełączasz odniesienia do submodułów, być może będziesz musiał znosić wiele rozwiązywania konfliktów.

Jesse Hallett
źródło
1
Dziękuję za rzucenie światła na to pytanie. Ma to teraz dla mnie całkowity sens, a polecenie resetowania działa idealnie w mojej sytuacji powyżej. Ale jakie byłyby polecenia, aby zaakceptować ref podmodułu z gałęzi głównej i wyrzucić ref do modułu podrzędnego bieżącej gałęzi? Wiem, jak radzić sobie z normalnymi konfliktami, ale po trzech dniach przeszukiwania sieci nie mogę znaleźć innego przykładu kodu niż rm -r. Zaczynam myśleć, że jest powód, dla którego przykłady nie istnieją; podmoduły są tak daleko oderwane od superprojektu, że musisz zarządzać każdym przejściem.
Tyler
26
WRESZCIE! Odpowiedź! Musiałem added by us: ../Mono.Cecilsię git statusjednak git addi git rmnie powiodło się Mono.Cecil: needs merge, pathspec 'Mono.Cecil/' did not match any files, ponieważ był tylko pusty folder i git naprawdę tylko pliki uchwyty. git checkoutdał mi Mono.Cecil: needs merge, error: you need to resolve your current index first, git submodule updatedał Skipping unmerged submodule Mono.Cecili git checkout master Mono.CecilWRESZCIE to naprawiłem. Podstawowy problem: git statussugestia jest błędna, więc wybierz gałąź i zabierz jej kopię folderu checkout!
IBBoard
6
@ Komenda IBBoard pomógł mi z tą sytuacją - Próbowałem git checkout --ours SUBMODi git add SUBMODi inni, ale w końcu robi git checkout master SUBMODstałe konflikt. Ten komentarz powinien być prawdopodobnie odpowiedzią, a nie komentarzem ... :)
Colin D Bennett
89

Cóż, technicznie nie zarządza konfliktami z modułami podrzędnymi (tj: zachowaj to, ale nie tamto), ale znalazłem sposób, aby kontynuować pracę ... i wszystko, co musiałem zrobić, to zwrócić uwagę na moje git statuswyjście i zresetować moduły podrzędne:

git reset HEAD subby
git commit

Spowoduje to zresetowanie modułu podrzędnego do zatwierdzenia przed ściągnięciem. Co w tym przypadku jest dokładnie tym, czego chciałem. A w innych przypadkach, w których potrzebuję zmian zastosowanych w module podrzędnym, zajmę się tymi ze standardowymi przepływami pracy podmodułu (wzorzec kasy, ściągnij żądany tag itp.).

Tyler
źródło
Wydaje mi się, że to tylko zmienia status modułu powodującego konflikt z „oba zmodyfikowane” na „usunięte”.
Matt Zukowski
4
Zamiast tego możesz zachować podmoduł scalonej gałęzi: git reset <merged-branch> subby
Edward Anderson
1
działa dla mnie zgodnie z opisem w odpowiedzi .. git reset HEAD path / to / submodule / dir
estoy
56

Trochę zmagałem się z odpowiedziami na to pytanie i nie miałem też szczęścia z odpowiedziami w podobnym poście SO . A więc to właśnie zadziałało - pamiętając, że w moim przypadku submoduł był utrzymywany przez inny zespół, więc konflikt pochodził z różnych wersji submodułu w master i mojej lokalnej gałęzi projektu, nad którym pracowałem:

  1. Biegać git status - zanotuj folder podmodułu z konfliktami
  2. Zresetuj podmoduł do wersji, która została ostatnio zatwierdzona w bieżącej gałęzi:

    git reset HEAD path/to/submodule

  3. W tym momencie masz wolną od konfliktów wersję swojego modułu podrzędnego, którą możesz teraz zaktualizować do najnowszej wersji w repozytorium modułu podrzędnego:

    ścieżka cd / do / podmoduł
    git submodule foreach git pull origin SUBMODULE-BRANCH-NAME
  4. A teraz możesz to zrobić commiti wrócić do pracy.

Emma Burrows
źródło
16

Najpierw znajdź skrót, do którego chcesz odwoływać się w swoim module podrzędnym. następnie uruchomić

~/supery/subby $ git co hashpointerhere
~/supery/subby $ cd ../
~/supery $ git add subby
~/supery $ git commit -m 'updated subby reference'

Pomogło mi to w doprowadzeniu mojego modułu podrzędnego do prawidłowego odniesienia skrótu i ​​kontynuowaniu pracy bez dalszych konfliktów.

hellatan
źródło
1
lub możesz po prostu zrobić kasę git - theirs (lub --ours) subby
Bachi
@Bachi: git checkout --theirs i --ours nie ma wpływu na moduły podrzędne.
Edward Anderson
1
Chociaż to rozwiązuje konflikt, nie jest łatwo określić <hashpointerhere>. Nie znam prostego sposobu, aby zobaczyć zatwierdzenie modułu podrzędnego po każdej stronie konfliktu. Każde zatwierdzenie, które wyrejestrujesz w subby, może różnić się od każdej strony scalenia, co nie jest odpowiednie w zatwierdzeniu scalającym.
Edward Anderson
@nilbus, to prawda. Porzuciliśmy pracę z modułami podrzędnymi git, ponieważ było to jedno z naszych zmartwień i bardzo utrudniło nam ustalenie, którego zobowiązania faktycznie chcesz. Użyliśmy narzędzia Composer (php) jako menedżera pakietów, co tak naprawdę mi się podoba, ponieważ tworzy plik blokujący, blokujący repozytoria do określonego skrótu. Jednak ponieważ używamy node_modules w wielu repozytoriach, napotkalibyśmy tu i tam moduły powodujące konflikt. Od tego czasu przeszliśmy na npm, aby zarządzać tymi rzeczami, ale jest to również cała inna puszka robaków.
hellatan
12

Miałem ten problem z git rebase -i origin/masteroddziałem. Chciałem wziąć podmoduł w wersji master, więc po prostu zrobiłem:

git reset master path/to/submodule

i wtedy

git rebase --continue

To rozwiązało problem.

maraton
źródło
3
To zadziałało dla mnie. Wciąż zastanawiam się, co zrobili, aby uszkodzić podmoduł
Checo R
3

Otrzymałem pomoc w tej dyskusji. W moim przypadku

git reset HEAD subby
git commit

pracował dla mnie :)

Mithun Das
źródło
2

W moim katalogu nadrzędnym widzę:

$ git status
On branch master
Your branch is up-to-date with 'origin/master'.
Unmerged paths:
(use "git reset HEAD <file>..." to unstage)
(use "git add <file>..." to mark resolution)

Więc właśnie to zrobiłem

git reset HEAD linux
Kjeld Flarup
źródło