Chciałbym zmienić nazwę / przenieść poddrzewo projektu w Git, przenosząc je z
/project/xyz
do
/components/xyz
Jeśli użyję zwykłego git mv project components
, cała historia zatwierdzeń xyz project
zgubi się. Czy istnieje sposób, aby przenieść to tak, aby historia była zachowana?
git mv
: stackoverflow.com/questions/1094269/whats-the-purpose-of-git-mvOdpowiedzi:
Git wykrywa zmiany nazw zamiast przetrwania operacji z zatwierdzeniem, więc czy używasz
git mv
czymv
nie ma znaczenia.log
Komenda bierze--follow
argument, że kontynuuje historię przed operacją zmiany nazwy, tzn wyszukuje podobnej treści używając heurystyki:http://git-scm.com/docs/git-log
Aby przejrzeć pełną historię, użyj następującego polecenia:
źródło
git config alias.logf "log --follow"
i po prostu napisaćgit logf ./path/to/file
.Jest to możliwe , aby zmienić nazwę pliku i przechowywać historię nienaruszone, chociaż powoduje zmianę nazwy pliku w całej historii repozytorium. Jest to prawdopodobnie tylko dla obsesyjnych miłośników git-logów i ma pewne poważne implikacje, w tym:
Ponieważ nadal jesteś ze mną, prawdopodobnie jesteś solistą, który zmienia nazwę całkowicie izolowanego pliku. Przenieśmy plik za pomocą
filter-tree
!Załóżmy, że zamierzasz przenieść plik
old
do folderudir
i nadać mu nazwęnew
Można to zrobić
git mv old dir/new && git add -u dir/new
, ale to łamie historię.Zamiast:
będzie przerobić każdy popełnić w branży, wykonujące polecenia w kleszcze dla każdej iteracji. Wiele rzeczy może się nie udać, gdy to zrobisz. Zwykle sprawdzam, czy plik jest obecny (w przeciwnym razie nie ma go jeszcze do przeniesienia), a następnie wykonuję niezbędne kroki, aby podeprzeć drzewo według moich upodobań. Tutaj możesz przeglądać pliki, aby zmieniać odniesienia do pliku itd. Ogłusz się! :)
Po zakończeniu plik zostanie przeniesiony, a dziennik pozostanie nienaruszony. Czujesz się jak pirat ninja.
Również; Oczywiście katalog mkdir jest konieczny tylko wtedy, gdy plik zostanie przeniesiony do nowego folderu. Jeśli pozwoli uniknąć tworzenia tego folderu wcześniej w historii niż plik istnieje.
źródło
--index-filter
for forames będzie znacznie szybsze, ponieważ drzewo nie będzie musiało być sprawdzane i włączane przy każdym zatwierdzeniu.--index-filter
działa bezpośrednio na każdy indeks zatwierdzenia.Nie.
Krótka odpowiedź brzmi NIE . Zmiana nazwy pliku w Git i zapamiętanie historii nie jest możliwa. I to jest ból.
Plotka głosi, że
git log --follow
--find-copies-harder
to zadziała, ale dla mnie to nie działa, nawet jeśli nie ma zerowych zmian w zawartości pliku, a ruchy zostały wykonanegit mv
.(Początkowo użyłem Eclipse do zmiany nazwy i aktualizacji pakietów w jednej operacji, co mogło pomylić Git. Ale to jest bardzo powszechna rzecz.
--follow
Wydaje się, że działa, jeśli tylko amv
jest wykonywane, a następnie acommit
imv
nie jest za daleko.)Linus mówi, że należy rozumieć całą zawartość projektu oprogramowania w sposób holistyczny, bez konieczności śledzenia poszczególnych plików. Niestety mój mały mózg nie może tego zrobić.
To naprawdę denerwujące, że tak wiele osób bezmyślnie powtórzyło stwierdzenie, że Git automatycznie śledzi ruchy. Zmarnowali mi czas. Git nie robi czegoś takiego. Zgodnie z projektem (!) Git w ogóle nie śledzi ruchów.
Moim rozwiązaniem jest zmiana nazw plików z powrotem na ich oryginalne lokalizacje. Zmień oprogramowanie, aby pasowało do kontroli źródła. Z Gitem wydaje się, że po raz pierwszy musisz to zrobić „dobrze”.
Niestety psuje to Eclipse, które wydaje się używać
--follow
.git log --follow
czasami nie wyświetla pełnej historii plików ze skomplikowanymi historiami zmian nazw, chociażgit log
tak jest. (Nie wiem dlaczego.)(Istnieją pewne zbyt sprytne hacki, które cofają się i wznawiają stare prace, ale są raczej przerażające. Zobacz GitHub-Gist: emiller / git-mv-with-history .)
źródło
pokaże historię poprzez zmianę nazw.
źródło
git mv
Zasadzie robigit rm && git add
. Istnieją opcje takie jak-M90
/,--find-renames=90
aby rozważyć zmianę nazwy pliku, gdy jest on w 90% identyczny.Ja robię:
źródło
-A
zamiast tego zachowanie ? Ponownie patrz tutaj: git-scm.com/docs/git-addgit add -u
. Dokumenty Git są zwykle nieprzydatne i są ostatnim miejscem, w którym chciałbym wyglądać. Oto jeden post pokazujący sięgit add -u
w akcji: stackoverflow.com/a/2117202 .Nie (8 lat później, Git 2.19, III kwartał 2018), ponieważ Git wykryje zmianę nazwy katalogu , co jest teraz lepiej udokumentowane.
Zobacz zatwierdzenie b00bf1c , zatwierdzenie 1634688 , zatwierdzenie 0661e49 , zatwierdzenie 4d34dff , zatwierdzenie 983f464 , zatwierdzenie c840e1a , zatwierdzenie 9929430 (27 czerwca 2018 r.) I zatwierdzenie d4e8062 , zatwierdzenie 5dacd4a (25 czerwca 2018 r.) Autorstwa Elijah Newren (
newren
) .(Połączone przez Junio C Hamano -
gitster
- w commit 0ce5a69 , 24 lipca 2018)Wyjaśnia to teraz
Documentation/technical/directory-rename-detection.txt
:Przykład:
Ale to wiele innych przypadków, takich jak:
Aby uprościć wykrywanie zmiany nazwy katalogu, Git wymusza te reguły:
kilka podstawowych zasad ogranicza się w przypadku wykrycia zmiany nazwy katalogu:
Możesz zobaczyć wiele testów
t/t6043-merge-rename-directories.sh
, które również wskazują, że:źródło
Cel
git am
Ograniczenie
Podsumowanie
git log --pretty=email -p --reverse --full-index --binary
cat extracted-history | git am --committer-date-is-author-date
1. Wyodrębnij historię w formacie wiadomości e-mail
Przykład: Historia Ekstrakt
file3
,file4
ifile5
Ustaw / wyczyść miejsce docelowe
Wyodrębnij historię każdego pliku w formacie e-mail
Niestety opcja
--follow
lub--find-copies-harder
nie można jej połączyć--reverse
. Dlatego historia jest wycinana, gdy nazwa pliku jest zmieniana (lub gdy nazwa katalogu nadrzędnego jest zmieniana).Historia tymczasowa w formacie e-mail:
Dan Bonachea sugeruje odwrócenie pętli polecenia generowania dziennika git w pierwszym kroku: zamiast uruchamiać dziennik git raz na plik, uruchom go dokładnie raz z listą plików w wierszu poleceń i wygeneruj pojedynczy zunifikowany dziennik. W ten sposób zatwierdzenia, które modyfikują wiele plików, pozostaną w wyniku pojedynczym zatwierdzeniem, a wszystkie nowe zatwierdzenia zachowają swoją pierwotną względną kolejność. Uwaga: wymaga to również zmian w drugim kroku poniżej podczas przepisywania nazw plików w (teraz ujednoliconym) dzienniku.
2. Zreorganizuj drzewo plików i zaktualizuj nazwy plików
Załóżmy, że chcesz przenieść te trzy pliki w tym drugim repozytorium (może to być to samo repo).
Dlatego zreorganizuj swoje pliki:
Twoja tymczasowa historia jest teraz:
Zmień także nazwy plików w historii:
3. Zastosuj nową historię
Twoje inne repo to:
Zastosuj zatwierdzenia z tymczasowych plików historii:
--committer-date-is-author-date
zachowuje oryginalne znaczniki czasu zatwierdzenia ( komentarz Dana Bonachei ).Twoje drugie repo to teraz:
Użyj,
git status
aby zobaczyć liczbę zatwierdzeń gotowych do wypchnięcia :-)Dodatkowa sztuczka: sprawdź przemianowane / przeniesione pliki w repozytorium
Aby wyświetlić listę plików, których nazwy zostały zmienione:
Więcej dostosowań: Możesz wykonać polecenie,
git log
używając opcji--find-copies-harder
lub--reverse
. Możesz także usunąć pierwsze dwie kolumny, używająccut -f3-
i grepując pełny wzór „{. * =>. *}”.źródło
Postępowałem zgodnie z tym wieloetapowym procesem, aby przenieść kod do katalogu nadrzędnego i zachować historię.
Krok 0: Utworzono gałąź „historia” z „głównego” do przechowywania
Krok 1: Użyłem narzędzia git-filter-repo do przepisania historii. To polecenie poniżej przeniosło folder „FolderwithContentOfInterest” o jeden poziom wyżej i zmodyfikowało odpowiednią historię zatwierdzeń
Krok 2: Do tego czasu repozytorium GitHub straciło ścieżkę zdalnego repozytorium. Dodano zdalne odniesienie
Krok 3: Wyciągnij informacje z repozytorium
Krok 4: Połącz lokalną utraconą gałąź z gałęzią początkową
Krok 5: Jeśli pojawi się monit, konflikt scalania adresu dla struktury folderów
Krok 6: Naciśnij !!
Uwaga: zmodyfikowana historia i przeniesiony folder wydają się być już zatwierdzone.
enter code here
Gotowy. Kod przenosi się do katalogu nadrzędnego / pożądanego, nie zmieniając historii!
źródło
Chociaż rdzeń Git, hydraulika Git nie śledzi nazw, historia, którą wyświetlasz za pomocą „porcelany” w dzienniku Git, może je wykryć, jeśli chcesz.
Dla danego
git log
zastosowania użyj opcji -M:Z bieżącą wersją Git.
Działa to w przypadku innych poleceń, takich jak
git diff
.Istnieją opcje, aby porównania były mniej lub bardziej rygorystyczne. Jeśli zmienisz nazwę pliku bez wprowadzania znaczących zmian w pliku w tym samym czasie, Git log i znajomi mogą wykryć zmianę nazwy. Z tego powodu niektórzy ludzie zmieniają nazwy plików w jednym zatwierdzeniu i zmieniają je w innym.
Korzystanie z procesora wiąże się z pewnym kosztem za każdym razem, gdy poprosisz Gita o znalezienie nazwy pliku, więc czy go użyjesz, czy nie, i kiedy to zależy od ciebie.
Jeśli chcesz, aby Twoja historia była zawsze raportowana z wykrywaniem zmiany nazwy w określonym repozytorium, możesz użyć:
Pliki przenoszenie z jednego katalogu do drugiego jest wykrywane. Oto przykład:
Pamiętaj, że działa to zawsze, gdy używasz diff, nie tylko z
git log
. Na przykład:W ramach próby dokonałem niewielkiej zmiany w jednym pliku w gałęzi funkcji i zatwierdziłem go, a następnie w gałęzi głównej zmieniłem nazwę pliku, zatwierdziłem, a następnie dokonałem niewielkiej zmiany w innej części pliku i dokonałem tego. Kiedy poszedłem do gałęzi funkcji i połączyłem z master, scalanie zmieniło nazwę pliku i połączyło zmiany. Oto wynik scalenia:
W rezultacie powstał katalog roboczy, którego nazwa pliku została zmieniona i dokonano obu zmian tekstu. Jest więc możliwe, że Git postąpi właściwie, mimo że nie śledzi wyraźnie zmian nazw.
To jest późna odpowiedź na stare pytanie, więc inne odpowiedzi mogły być w tym czasie prawidłowe dla wersji Git.
źródło
Najpierw utwórz samodzielne zatwierdzenie, zmieniając tylko nazwę.
Następnie wszelkie ewentualne zmiany zawartości pliku umieszczane w osobnym zatwierdzeniu.
źródło
Aby zmienić nazwę katalogu lub pliku (niewiele wiem o skomplikowanych przypadkach, więc mogą istnieć pewne zastrzeżenia):
Aby zmienić nazwę katalogu w plikach, które go wspominają (możliwe jest użycie wywołań zwrotnych, ale nie wiem jak):
expressions.txt
to plik wypełniony liniami typuliteral:OLD_NAME==>NEW_NAME
(możliwe jest użycie RE w Pythonie zregex:
lub glob zglob:
).Aby zmienić nazwę katalogu w wiadomości commits:
Obsługiwane są również wyrażenia regularne Pythona, ale muszą być one napisane ręcznie w Pythonie.
Jeśli repozytorium jest oryginalne, bez zdalnego, będziesz musiał dodać,
--force
aby wymusić przepisanie. (Możesz to zrobić przed utworzeniem kopii zapasowej repozytorium).Jeśli nie chcesz zachować referencji (będą one wyświetlane w historii oddziału Git GUI), musisz dodać
--replace-refs delete-no-add
.źródło
Po prostu przenieś plik i etap za pomocą:
Przed zatwierdzeniem możesz sprawdzić status:
To pokaże:
Testowałem z Git w wersji 2.26.1.
Wyodrębniono ze strony pomocy GitHub .
źródło
Robię przenoszenie plików, a następnie robię
które umieszczają w obszarze przesiewania wszystkie usunięte / nowe pliki. Tutaj git zdaje sobie sprawę, że plik został przeniesiony.
Nie wiem dlaczego, ale to działa dla mnie.
źródło