Niedawno dowiedziałem się, że podczas łączenia dwóch gałęzi w git, jeśli są zmiany w dwóch sąsiednich liniach, git ogłasza ten konflikt. Na przykład jeśli plik test.txt
ma tę treść:
Line 1: A
Line 2: B
Line 3: C
Line 4: D
w oddziale master
zmieniamy to na
Line 1: A
Line 2: B1
Line 3: C
Line 4: D
podczas gdy w oddziale testing
zmieniamy to na
Line 1: A
Line 2: B
Line 3: C1
Line 4: D
a następnie spróbuj połączyć testing
się master
, git ogłasza konflikt scalenia. Moim naiwnym oczekiwaniem było, że połączenie nastąpi bez konfliktu i przyniesie to:
Line 1: A
Line 2: B1
Line 3: C1
Line 4: D
Jestem pewien, że istnieje dobry powód, dla którego git nie łączy się w ten sposób. Czy ktoś może wyjaśnić ten powód?
Odpowiedzi:
Zakładając, że ten fragment kodu
został zmieniony w jednym oddziale na to
i w innej gałęzi
wtedy nie chciałbym, żeby git połączył to z tym
nie alarmując mnie.
Aby uniknąć takich problemów, git zwykle odmawia automatycznego scalania zmian dotykających pobliskich linii. Daje to szansę sprawdzenia, czy logika programu byłaby zepsuta, czy nie.
Ten przykład jest trywialny, ale podczas łączenia ogromnych gałęzi ryzyko podobnych „logicznych” konfliktów jest znacznie większe. Czasami chciałbym nawet, aby kontekst był jeszcze większy niż obecnie.
źródło
Czy to zachowanie dotyczy tylko gitów?
Po dyskusji z kolegą właśnie próbowałem, a SVN radzi sobie z tym bez problemu: modyfikujesz 2 linie.
Możliwości scalania kilku VCS są testowane tutaj dla bazaru, darcs, git i mercurial : https://github.com/mndrix/merge-this
Wydaje się, że tylko darcy skutecznie łączą przypadek „linii sąsiednich”.
Zastosowanie sąsiednich zmian do plików nie jest trudnym problemem. Naprawdę uważam, że to zachowanie zostało wybrane celowo.
Dlaczego ktoś miałby decydować, że modyfikacja sąsiednich linii powoduje konflikt?
Myślę, że to zmusza cię do spojrzenia na to .
Modif numer 1, na module głównym:
Zmodyfikowany numer 2, scalony z oddziału:
Po scaleniu nie chcesz tego:
Widząc to zachowanie jako funkcję
Możesz zmienić zachowanie łączenia git na korzyść. Jeśli musisz zachować spójność 2 linii, ale nie możesz ich wykryć (w czasie kompilacji, na początku testów lub w innym przypadku), możesz spróbować dołączyć do nich.
Przepisz to ...:
...do tego:
Więc kiedy scalisz Mod 1 ...:
... z Modif 2 ...:
..., git wywoła konflikt, a ty zmusisz cię do obejrzenia go.
źródło
Głównie zgaduję, ale myślę, że ma to związek z tym, że linia 2 jest używana jako kontekst dla zmiany linii 3.
Git nie może po prostu powiedzieć, że „Linia z C stała się linią z C1”, ponieważ może istnieć inna linia z „C”, więc mówi „Linia z C, to jest zaraz po rozpoczęciu pliku, linia z A, a linia z B jest teraz C1 ”
Jeśli „linii z B” już nie ma, część kontekstu zostanie utracona, a git może jedynie z grubsza określić, gdzie ma iść nowa linia.
źródło
Pozostałe odpowiedzi tutaj są trafne, ale dla mnie zawsze wydawało się to niepotrzebnym ograniczeniem.
Jak powiedzieli inni, w tych przypadkach zdecydowanie nie chcesz, aby Git scalił linie bez ostrzeżenia.
Ale po otrzymaniu ostrzeżenia nadal chciałem zrobić to automatycznie. Napisałem więc niestandardowy sterownik scalania git, który może scalać konflikty na sąsiednich (lub pojedynczych) liniach interaktywnie:
Oszczędza mi to dużo czasu, ponieważ zarządzam projektem, w którym ludzie często pracują nad tymi samymi plikami i refaktoryzują dużo kodu.
Skrypt jest dostępny na GitHub na licencji GPLv3 +. Może uznasz to za przydatne:
https://github.com/paulaltin/git-subline-merge
źródło