2013-01-08 11 views
18

Mam projekt, w którym początkowo używałem submodułów dla kodu zależnego. Okazuje się, że submoduły nie są odpowiednie dla tego projektu (i są trudne do zastosowania w praktyce), więc zamieniam każdy moduł częściowy na poddrzewo (przy użyciu nowej funkcji git-subtree).Błąd łączenia po przekonwertowaniu modułu podrzędnego Git do poddrzewa

W moim roboczym repozytorium pomyślnie usunąłem każdy moduł pomocniczy i dodałem stare repozytorium częściowe jako poddrzewo. Nie ma problemu z tym.

Kiedy udać się do innego klonu i próbować wyciągnąć z pierwszego, pojawia się następujący błąd na etapie scalania:

error: The following untracked working tree files would be overwritten by merge: 
     sub/.gitignore 
     sub/Makefile 
     sub/README 
     sub/src/main.c 
     ... and so on for all files in sub/ 
Aborting 

Wydaje się, że to dlatego, że pliki w sub/ naprawdę nigdy nie istniał główne repozytorium, a kiedy Git stosuje łatę do aktualizacji .gitmodules, nie usuwa katalogu z plikami modułów. Podczas przetwarzania następnego zatwierdzenia, w którym Git próbuje utworzyć nowe pliki, które są teraz częścią głównego repozytorium, wszystkie te pliki kolidują z wciąż istniejącymi plikami w sub/.

Rozwiązanie, które znalazłem, to użycie rm -rf sub przed git pull, co pozwala uniknąć tego problemu.

Moje pytanie brzmi: czy istnieje przełącznik linii poleceń, z którego można korzystać pod numerem git merge z napisem "Zastąp wszystkie pliki, które istnieją w katalogu roboczym"? Jeszcze lepiej będzie funkcja, w której git merge będzie wyglądać zawartość istniejącego pliku, a jeśli zawartość jest identyczna z pliku, który miał utworzyć mimo to, pomiń komunikat o błędzie i kontynuować.

UPDATE: Stworzyłem repozytoriów Git, które pokazują ten problem, aby pokazać dokładnie to, co mówię. Aby odtworzyć:

$ git clone https://github.com/ghewgill/q14224966.git 
$ cd q14224966 
$ git submodule init 
$ git submodule update 
$ git merge origin/branch 

ta powinna skutkować komunikatem o błędzie

error: The following untracked working tree files would be overwritten by merge: 
    sub/Makefile 
    sub/README 
    sub/src/main.c 
Please move or remove them before you can merge. 
Aborting 
+0

Próbowałeś to: http://goo.gl/z1XP9? – Efthymis

+0

@Eththisis: Pełny link to http://stackoverflow.com/questions/1295171/git-merge-to-master-while-automatically-choosing-to-overwrite-master-files-with (proszę nie używać adresu URL skróty tutaj). Próbowałem 'git merge -s recursive -X ich origin/master' i wystąpił ten sam błąd. –

+0

Przepraszam za to – Efthymis

Odpowiedz

9

Znam twoje pytanie było konkretne scalić, ale miałem podobne problemy z łączących submodules git. Myślę, że to rozwiązanie zadziała z twoim problemem, nawet jeśli nie odnosi się bezpośrednio do pytania o scalenie.

Znalazłem, że przez przymusowe sprawdzenie gałęzi, którą chcesz scalić, a następnie powrót do mistrza, wszystko działa z submodułami.

dostać rzeczy działa w swoim przykładzie:

$ git clone https://github.com/ghewgill/q14224966.git 
$ cd q14224966 
$ git submodule init 
$ git submodule update 
$ git checkout -f origin/branch 
$ git checkout master 
$ git merge origin/branch 

To działa, ponieważ jest to w zasadzie robi swój krok dla ciebie rm -rf. To prawda, że ​​jest to trochę okrężne i może nie warto tego robić, jeśli masz tylko jeden submoduł taki jak twój przykład. Ale okazało się, że jest to dość czasochłonne, gdy pracuję w projekcie z wieloma submodułami.

Ponadto, jak zostało wskazane w komentarzach, jeśli chcesz uniknąć wprowadzania zmian do drzewa pracy, można użyć to:

$ git clone https://github.com/ghewgill/q14224966.git 
$ cd q14224966 
$ git submodule init 
$ git submodule update 
$ git reset origin/branch 
$ git reset --hard master 

Działa to mniej więcej w ten sam sposób, ale unika sprawdzenia inne pliki w procesie.Nie miałem okazji używać tego na wolności, ale wydaje się, że to metoda dźwiękowa.

Istnieje również $ git merge -s subtree origin/branch. Działa na twoim przykładzie, ale miałem nieoczekiwane wyniki, gdy zaangażowano więcej niż jeden submoduł. Możesz jednak mieć więcej szczęścia.

+1

Zajęło mi rytm, aby zobaczyć punkt, aby zobaczyć, jak sprytna jest ta metoda. Zauważyłem teraz, że możesz zastąpić kasę 'origin origin/branch git reset; git reset --hard master'; unika się wszystkich czynności związanych z pracą, z wyjątkiem pożądanych skreśleń. – jthill

+0

@jthill Masz rację. Możesz całkowicie pominąć elementy drzewa roboczego, używając zamiast tego resetowania.Zaktualizuję moją odpowiedź, aby to odzwierciedlić. Dzięki! –

+0

Niestety, drugie rozwiązanie używające 'git reset' nie działa, ponieważ odrzuca wszelkie zmiany wprowadzone w gałęzi' master' (na przykład do 'README') po utworzeniu gałęzi. –

1

Nie można uzyskać git-merge (ani żadnego innego polecenia) na wymuszone pliki clobber, o których nie sądzi, że nie. git stara się bardzo ciężko nie robić nic, całkowicie nieodwracalnie.

Ale z wielu podmodułów można dokonać skreślenia nieco łatwiejsze i bezpieczniejsze z git submodule foreach:

$ git submodule foreach 'rm -rf $toplevel/$path' 
Entering 'sub' 
$ git merge origin/branch 
Updating a231acd..6b4d2f4 
Fast-forward 
... 
+0

To czyni nieco 'rm -rf' nieco łatwiejszym, ale wciąż jest to samo rozwiązanie. –

+0

Niestety, tak. ale będziesz musiał zrobić coś specjalnego dla tej sytuacji, więc równie dobrze może to zrobić najprostsza rzecz, która działa – Eevee

0

próbował

git sprowadzić --all resetu

git --hard origin/master

ale to nie działa.

można wykorzystywać strategię scalania 'nasz':

git merge -s ours starym panem

Można również użyć git-zapas, aby zapisać zmiany, a następnie git-stash zastosowanie do ich przywrócenia.

+0

Użycie 'merge -s ours' w ogóle nie powoduje scalenia i nie rozwiązuje problemu. –

+0

tak, jest to problem, którego nie można scalić: D, ale czy próbowałeś ukryć? – GLES

+0

Niestety, przechowywanie nie pomaga, ponieważ nadal musisz wykonać * jakiś rodzaj scalenia, kiedy się rozpakujesz. –

1

(Zastrzeżenie: Nigdy nie pracowałem z poddrzew i nie wiem, jak skomplikowany jest rzeczywista repo, więc te rozwiązania mogą nie działać właściwie dla ciebie.)

Od zabawy z próbki repo, Znalazłem dwa rozwiązania, które zarówno wydaje się działać, choć produkują różne popełniają drzew:

  1. Zastosowanie git merge -s resolve origin/branch

    ~/q14224966[master]> git reset --hard origin/master 
    HEAD is now at a231acd add submodule 
    ~/q14224966[master]> touch other.c && git add . && git commit -m "New commit." 
    [master bc771ac] New commit. 
    0 files changed 
    create mode 100644 other.c 
    ~/q14224966[master]> git merge -s resolve origin/branch 
    Trying really trivial in-index merge... 
    error: Merge requires file-level merging 
    Nope. 
    Trying simple merge. 
    Simple merge failed, trying Automatic merge. 
    Adding sub/Makefile 
    Adding sub/README 
    Adding sub/src/main.c 
    Merge made by the 'resolve' strategy. 
    .gitmodules | 3 --- 
    sub   | 1 - 
    sub/Makefile | 1 + 
    sub/README  | 1 + 
    sub/src/main.c | 1 + 
    5 files changed, 3 insertions(+), 4 deletions(-) 
    delete mode 160000 sub 
    create mode 100644 sub/Makefile 
    create mode 100644 sub/README 
    create mode 100644 sub/src/main.c 
    ~/q14224966[master]> ls 
    README main.c other.c sub/ 
    ~/q14224966[master]> cd sub/ 
    ~/q14224966/sub[master]> ls 
    Makefile README src/ 
    ~/q14224966/sub[master]> git status 
    # On branch master 
    # Your branch is ahead of 'origin/master' by 5 commits. 
    # 
    nothing to commit (working directory clean) 
    ~/q14224966/sub[master]> cd .. 
    ~/q14224966[master]> git status 
    # On branch master 
    # Your branch is ahead of 'origin/master' by 5 commits. 
    # 
    nothing to commit (working directory clean) 
    

    Oto resul ting popełnić drzewo: git commit tree - merge option

  2. Użyj rebase zamiast seryjnej:

    ~/q14224966[master]> git reset --hard origin/master 
    HEAD is now at a231acd add submodule 
    ~/q14224966[master]> touch other.c && git add . && git commit -m "New commit." 
    [master ae66060] New commit. 
    0 files changed 
    create mode 100644 other.c 
    ~/q14224966[master]> git rebase origin/branch 
    First, rewinding head to replay your work on top of it... 
    Applying: New commit. 
    ~/q14224966[master]> ls 
    README main.c other.c sub/ 
    ~/q14224966[master]> cd sub/ 
    ~/q14224966/sub[master]> ls 
    Makefile README src/ 
    ~/q14224966/sub[master]> git status 
    # On branch master 
    # Your branch is ahead of 'origin/master' by 4 commits. 
    # 
    nothing to commit (working directory clean) 
    ~/q14224966/sub[master]> cd .. 
    ~/q14224966[master]> git status 
    # On branch master 
    # Your branch is ahead of 'origin/master' by 4 commits. 
    # 
    nothing to commit (working directory clean) 
    

    Oto wynikające popełnić drzewa: git commit tree - rebase option

+0

Próbowałem użyć 'merg -s resolve', ale to nie działa, jeśli pliki z modułu są nadal dostępne (upewnij się, że zaczynasz od' git reset - hard origin/master && rm -rf sub && git aktualizacja modułu') . –

Powiązane problemy