Automatyczne generowanie opisu commita przy git merge

Krótko, lecz treściwie: odkryłem przełącznik --log=n  przy git merge.

Będąc na feature branchu opisuję dokładnie zmiany wraz ze znacznikami zagadnienia, co potem jest przetwarzane Redmine’a. Niestety, przy wykonywaniu merge’a do mastera sugerowana jest domyślna treść, którą nadpisywałem skopiowanym opisem któregoś z ostatnich commitów w branchu.

Aż do wczoraj. Kolejny raz przeczytałem manual i doszukałem się w nim ww. przełącznika. W moim przypadku wystarczy więc wykonać merge’a poprzez:

git merge --log=n redmine-XXXXX

Dzięki temu do domyślnej treści merge’owego commita dopisywana jest lista opisów ostatnich n commitów z tego brancha.

3-way merge przy aplikowaniu patcha w git

Nigdy nie rozumiałem sensu używania git apply. Kiedyś zastanawiałem się, czy ma jakieś zalety w stosunku do sprawdzonego patcha. Przejrzałem wtedy nawet pobieżnie manuala stwierdzając, że jest tam przecież tylko to, co ma sam patch. W swojej pracy używałem więc sprawdzonego i dobrze znanego patcha.

Dopiero niedawno uświadomiłem sobie, że pominąłem chyba najistotniejszy przełącznik: -3 . Jego użycie powoduje (w przypadku, gdy diff nie aplikuje się wprost) wykonanie 3-way merge’a. W wielu przypadkach samoczynnie rozwiązuje to problem z aplikowaniem diffów, których nie dałoby się zastosować przy użyciu samego patcha.

Cofanie błędnego merge’a w git-svn

Kolejny wpis oparty na ostatnich doświadczeniach z pracy. Tym razem dość klasycznie: stworzyłem w swoim repozytorium git feature brancha na podstawie brancha testing zamiast mastera. Do testing – jak łatwo się domyślić – domerdżowuję feature branche przed przekazaniem ich do testów, w związku z tym jest tam zawsze co najmniej kilka modyfikacji czekających na przetestowanie.

Niestety, zorientowałem się o tym dopiero po merge’u ww. feature brancha do mastera oraz wykonaniu git svn dcommit  (korzystam z git-svn), więc całość została nie tylko u mnie, ale też poszła do SVN-a. Sam git reset do commita sprzed merge’owania niewiele pomógł, ponieważ każdy git svn rebase i tak wracał do pierwotnego ustawienia HEAD.

Na początek, żeby pozbyć się nieprzetestowanych zmian z repozytorium SVN-a, wygenerowałem odwrotnego diffa:

git diff --no-prefix HEAD HEAD~1 > ~/revert.diff

I spatchowałem kod w masterze:

patch -p0 < ~/revert.diff

Po czym dodałem i scommitowałem zmiany w masterze oraz wypchnąłem je do SVN-a przez:

git svn dcommit

(można to było zrobić poprzez git reset lub git revert, jednak to był sposób, z którego mogłem skorzystać bez przeglądania dokumentacji, a ciągle istniało ryzyko, że ktoś ten kod w międzyczasie pobierze)

Mając stan SVN-a sprzed błędnego merge’a, przeszedłem do wertowania internetu.

Rozwiązaniem okazało się cofnięcie HEAD w gicie do ostatniego commita sprzed merge’a:

git reset --hard commit_hash

A następnie wykonanie tego samego dla SVN-owego remote’a. W tym celu należy użyć

git svn reset -r svn_revision_id

gdzie svn_revision_id  to ID ostatniej rewizji SVN sprzed błędnego merge’a.

Dzięki temu zarówno repozytorium git, jak i lokalny remote wskazują na stan sprzed merge’a. Wykonanie:

git svn rebase

pobierze więc kolejne commity z SVN na nowo i nie będzie przestawiało HEAD-a w niepożądane miejsce.

Z racji tego, że mój feature branch posiadał błędnego rodzica, do przeniesienia zmian na mastera skorzystałem z cherry-pick:

git cherry-pick commit_hash