2015-06-20 5 views
5

Próbuję zgnieść wiele commitów w jeden, problem polega na tym, że muszę to zrobić przez autora (imię i nazwisko lub adres e-mail).Git Squash według autora - Wszyscy autorzy zatwierdzają do jednego zatwierdzenia

postępowania:

Powiedzmy mam oddział o nazwie funkcja-a, w tej branży mam wiele zobowiązuje dla wielu autorów. Jak mogę zgnieść wszystkie zatwierdzenia przez autora (na przykład e-mail) do jednego zatwierdzenia. Chcę to zrobić, aby móc połączyć wszystkie autorytety w mistrza.

Każda pomoc tutaj?

góry dzięki

+0

Brzmi to tak, jakby mogło to prowadzić do niepotrzebnego wysiłku. Oznacza to, że jeśli zobowiązania danego autora nie są kolejne, to ich zgniecenie będzie wymagać dużej ręcznej interwencji. Lepiej byłoby, gdyby wielu autorów pracowało we własnym oddziale. – larsks

Odpowiedz

1

Be careful rewriting history

Koniec spowodować chcesz może być możliwe, jeśli tworzyć oddziały dla każdego autora, cherry-pick te rewizje od każdego autora do prawej gałęzi, a następnie zgnieść te zmiany. Jednak nie sądzę, że to zadziała, jeśli te zobowiązania znacząco zależą od siebie nawzajem.

Jeśli masz serię zatwierdzeń:

  Author1    Author2    Author1 
version1 ---commit---> version2 ---commit---> version3 ---commit--->... 

Jeśli było spróbować wyodrębnić zmiany z Author2 i zastosować je do version1, istnieje duża szansa, że ​​nie ma sensu (na przykład , jeśli Author2 modyfikuje kod, który utworzył Author1).

1

Z Kenkron „s caveats na uwadze, można zrobić:

SORTED_GIT_LOGS=$(git log --pretty="format:%an %H" master..feature_a | sort -g | cut -d' ' -f2); \ 
IFS=$(echo -en "\n\b"); for LOG in $SORTED_GIT_LOGS; do \ 
    git cherry-pick $LOG; \ 
done | less 

git log --pretty="format:%an %H" master..feature_a | sort -g by posortować dzienniki feature_a zatwierdzeń (nie te z master powodu składni master..feature_a)

Nadal musisz wykonać interaktywny rebase, aby zgnieść (teraz zamówione przez autora) na master.

+0

Przykład interaktywnego rebase: http://denniskubes.com/2012/08/2/2/honey-i-squashed-the-commits/ – VonC

+0

Jeśli zrobione przez autora, "git reset" może również działać: http: // makandracards .com/makandra/527-squash-kilka-git-commit-into-a-single-commit – VonC

1

Potrzebowałem zrobić podobny przepis na niepotrzebnie duże repozytorium, podczas gdy repo była w trybie offline. Podejście, które podjąłem, było próbą zautomatyzowanego "interaktywnego" rebase przy użyciu GIT_SEQUENCE_EDITOR, który jest objęty w this answer przez @ james-foucar & @ pfalcon.

Aby to działało dobrze, lepiej było najpierw usunąć scalenia z sekcji przepisywanej historii. Dla mojego własnego przypadku zostało to zrobione przy użyciu dużej liczby git rebase --onto, która jest obszernie omówiona w innych kwestiach dotyczących StackOverflow.

stworzyłem small script generate-similiar-commit-squashes.sh do generowania pick & squash polecenia tak, że kolejne podobne commity będzie ściśnięty. Użyłem author-date-and-shortlog, aby dopasować podobne zatwierdzenia, ale potrzebujesz tylko autora (mój komentarz ma komentarz o tym, jak dopasować go tylko do autora).

$ generate-similiar-commit-squashes.sh > /tmp/git-rebase-todo-list 

Wyjście wygląda

... 
pick aaff1c556004539a54a7a33ce2fb859af0c4238c [email protected] 
squash aa190ea2323ece42f1cd212041bf61b94d751d5c [email protected] 
pick aab8c98981a8d824d2bc0d5278d59bc1a22cc7b0 [email protected]_config.yml 

Repozytorium było również pełne self-powraca z tym samym stylu „xyz” Aktualizacja popełnienia wiadomości. Gdy zostały zgniecione, skutkowały pustymi zobowiązaniami.

Przeprowadzane przeze mnie zatwierdzenia miały identyczne komunikaty zatwierdzenia. git rebase -i oferuje poprawiony komunikat zatwierdzenia z dołączonymi wszystkimi komunikatami zatwierdzenia typu zgniecenia, które byłyby powtarzalne. Aby rozwiązać ten problem, użyłem małego skryptu perl z this answer, aby usunąć zduplikowane linie z komunikatu zatwierdzenia oferowanego przez git rebase. Jest lepiej w pliku, ponieważ będzie używany w zmiennej powłoki.

$ echo 'print if ! $x{$_}++' > /tmp/strip-seen-lines.pl 

teraz na końcowym etapie:

$ GIT_EDITOR='perl -i -n -f /tmp/strip-seen-lines.pl ' \ 
    GIT_SEQUENCE_EDITOR='cat /tmp/git-rebase-todo-list >' \ 
    git rebase --keep-empty -i $(git rev-list --max-parents=0 HEAD) 

Pomimo zastosowania --keep-empty, git skarżył się kilka razy w tym procesie o pustych zobowiązuje. Zrzuciłbym mnie na konsolę z niekompletnym git rebase. Aby pominąć puste zatwierdzanie i wznowić przetwarzanie, potrzebne były następujące dwa polecenia (raczej często w moim przypadku).

$ git reset HEAD^ 
$ GIT_EDITOR='perl -i -n -f /tmp/strip-seen-lines.pl ' git rebase --continue 

Ponownie mimo --keep-empty, znalazłem had no empty commits w końcowym historii git, więc resetuje powyżej usunął je wszystkie. Zakładam, że coś jest nie tak z moim gitem, wersja 2.14.1. Przetwarzanie ~ 10000 takich zatwierdzeń zajęło nieco ponad 10 minut na brzydkim laptopie.

+0

Interesujące podejście, bardziej kompletne niż moja odpowiedź. +1. Nie jestem jednak pewien co do twojego problemu z opcją '--keep-empty'. – VonC

+0

Warto również zwrócić uwagę na przepisanie historii w dowolnym momencie, jeśli nie chcesz, aby proces przepisywania przypisywał się (przepisującemu) jako operatorowi przy każdym zatwierdzeniu, prawdopodobnie konieczne będzie dokończenie przepisywania przez zresetowanie programu przekazującego. Najprostszą metodą jest [setting committer = author autor] (https://stackoverflow.com/a/32944640/5037965), ale potrzebne będzie bardziej złożone podejście, jeśli pierwotna informacja o komisarzu była rzeczywiście ważna i musi zostać zachowana. –

+0

Dodałem do https://gist.github.com/jayvdb/9b41677f00065dbd94cc02446fc5ba34 skrypt 'generate-multiple-new-file-squashes.sh', aby scalić zatwierdzenia składające się tylko z kolejnych dodanych elementów (tj. Program Commiter użył GitHub/GitLab/BitBucket Web UI "upload file") –