git rebase po poprzednim scaleniu git

79

Mam następującą sytuację:

  • Stworzyłem clone(Y) z głównego repozytorium (X), ponieważ na Y pracowało wiele osób, a my nie robiliśmy rebasetylko merges. Kiedy chcemy dostarczyć ( push) Y do X, chcielibyśmy zrobić rebase, aby wszystko było ładne i czyste

Problem polega na tym, że kiedy to robimy, rebasejesteśmy proszeni o wykonanie wszystkich połączeń, które już wykonaliśmy w poprzednich mergekrokach. Czy istnieje rozwiązanie tego problemu, oprócz tego, które oznacza ponowne wykonanie scalenia?

Spodziewałem się, że będzie to całkiem proste, ponieważ rozwiązaliśmy już konfliktowe połączenia.

INS
źródło
W: „Ponieważ było wielu ludzi pracujących nad Y, nie zrobiliśmy żadnej rebase, a jedynie scaliliśmy”, masz na myśli scalenie z wyższą wersją, czy to wszystko?
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功

Odpowiedzi:

80

Rebasing w celu uzyskania „czystej” historii jest przeceniany. Najlepszym sposobem, jeśli chcesz zachować historię, jest po prostu scalenie zamiast ponownego bazowania. W ten sposób, jeśli kiedykolwiek będziesz musiał wrócić do wersji, będzie ona dokładnie taka sama, jak ta, którą przetestowałeś podczas programowania. To również rozwiązuje problem dotyczący wcześniej rozwiązanych konfliktów scalania.

Jeśli nie zależy Ci na zachowaniu historii, możesz utworzyć nową gałąź poza wzorcem, sprawdzić ją, a następnie git read-tree -u -m devzaktualizować drzewo robocze, aby pasowało do devgałęzi. Następnie możesz przypisać wszystko do jednego dużego zatwierdzenia i połączyć go z głównym w normalny sposób.

Karl Bielefeldt
źródło
1
To, co tutaj skutecznie zrobiłeś, to połączenie. Nowa gałąź jest niepotrzebna.
isak gilbert
1
@isakgilbert To samo dotyczy tylko połączenia z --squash. Zwykłe scalanie doda N lub N + 1 zatwierdzeń do mastera, jeśli w gałęzi było N zatwierdzeń. Powyższa sugestia, lub merge --squash, zawsze doda tylko jedno zatwierdzenie do mastera.
peterflynn
3
@ytpete, tak dokładnie. Wydaje mi się, że powyższe to tylko okrężny sposób na dokonanie scalenia - przejście od dewelopera do mistrza. „Tworzenie nowej gałęzi” wskazuje po prostu to samo miejsce, w którym znajduje się master. „Zatwierdź wszystko w jednym dużym zatwierdzeniu” to po prostu zrobienie squasha.
isak gilbert
3
zatwierdzenia scalania są głośne, gdy próbujesz zobaczyć pełny zestaw zmian w jednej gałęzi. Trudno jest wyodrębnić różnicę i spojrzeć na nią, gdy czysta historia ułatwia to.
Ajax
2
Nie mogę się bardziej nie zgodzić z tym, że „czysta” historia jest przereklamowana. Nie jest przeceniony, oszczędza czas i sprawia, że ​​wszystko jest mniej zagmatwane.
basickarl
121

git merge --squashjest teraz moim preferowanym sposobem zmiany bazy po dużej ilości pracy i wielu połączeniach ( zobacz tę odpowiedź ). Jeśli gałąź, nad którą pracujesz, jest wywoływana my-branchi chcesz zmienić bazę, masterwykonaj następujące czynności:

git checkout my-branch
git branch -m my-branch-old
git checkout master
git checkout -b my-branch
git merge --squash my-branch-old
git commit
Jon Lemmon
źródło
13

Dwie uwagi:

  • możesz zmienić bazę swojej własnej (jeszcze nie wypchniętej) pracy tyle razy, ile chcesz, oprócz nowo pobranych zatwierdzeń.
  • Możesz uniknąć konfliktów scalania (podczas rebase), gdybyś został aktywowanygit rerere , co jest zrobione w tego rodzaju sytuacjach.
    http://git-scm.com/images/rerere2.png Zobacz więcej na git rerere.
VonC
źródło
@lulian: w takim przypadku, jeśli będziesz musiał zmienić bazę swojej pracy, myślę, że będziesz musiał ponownie wykonać te scalanie rozwiązań konfliktów.
VonC
@krlmlr Dziękuję. Przywróciłem łącze, dodałem ilustrację i odniesienie do strony podręcznika man tego polecenia.
VonC,
9

Możesz wziąć wszystkie zmiany w swojej gałęzi i umieścić je w nowym zatwierdzeniu w masternastępujący sposób:

git diff master > my_branch.patch
git checkout master
patch -p1 < my_branch.patch

Następnie przygotuj swoje pliki i zatwierdź.

dbaston
źródło
1

Jeśli chodzi o odtwarzanie konfliktów scalania, możesz użyć git rerere, aby zachować bazę danych, w jaki sposób konflikty scalania zostały już rozwiązane, dzięki czemu wykonanie ponownego bazowania, które powoduje te same konflikty, będzie wymagało automatycznego wykonania pracochłonnych części.

https://hackernoon.com/fix-conflicts-only-once-with-git-rerere-7d116b2cec67

git config --global rerere.enabled true

Jedyną rzeczą, na którą należy zwrócić uwagę, jest to, że jeśli rozwiązałeś coś niepoprawnie , następnym razem zostanie to automatycznie zablokowane i możesz nie zdawać sobie z tego sprawy.

Bardziej formalna dokumentacja tutaj: https://git-scm.com/docs/git-rerere

Ajax
źródło