Jak skopiować wersję jednego pliku z jednej gałęzi git do drugiej?


943

Mam dwie gałęzie, które są całkowicie połączone.

Jednak po zakończeniu scalania zdaję sobie sprawę, że jeden plik został pomieszany przez scalanie (ktoś inny dokonał automatycznego formatowania, gah), i łatwiej byłoby przejść do nowej wersji w drugiej gałęzi i następnie ponownie wstaw moją zmianę jednej linii po przeniesieniu jej do mojego oddziału.

Więc jak najłatwiej to zrobić w git?


3
Należy pamiętać, że w zaakceptowanej odpowiedzi pierwsze rozwiązanie wprowadza zmiany, a drugie nie. stackoverflow.com/a/56045704/151841
user151841

Odpowiedzi:


1672

Uruchom to z gałęzi, w której chcesz, aby plik się skończył:

git checkout otherbranch myfile.txt

Ogólne wzory:

git checkout <commit_hash> <relative_path_to_file_or_dir>
git checkout <remote_name>/<branch_name> <file_or_dir>

Niektóre uwagi (z komentarzy):

  • Za pomocą skrótu zatwierdzania możesz pobierać pliki z dowolnego zatwierdzenia
  • Działa to w przypadku plików i katalogów
  • nadpisuje plik myfile.txtimydir
  • Symbole wieloznaczne nie działają, ale działają ścieżki względne
  • Można podać wiele ścieżek

alternatywa:

git show commit_id:path/to/file > path/to/file

13
Tak, to by było. Ale taka była intencja pytania.
Ikke

37
Prawdopodobnie oczywiste, ale musisz użyć pełnej nazwy pliku ... Symbole wieloznaczne nie działają!
Chris Hart

6
chociaż .. to także fajny sposób: git show commit_id: ścieżka / do / pliku> ścieżka / do / pliku
milushov

14
zdalne: git checkout origin / otherbranch myfile.txt
Roman Rhrn Niestierow

6
Używanie symboli wieloznacznych działa, wystarczy je owinąć, ''aby nie zostały zinterpretowane przez powłokę.
Wiktor Czajkowski

82

Skończyło się na tym pytaniu podczas podobnych poszukiwań. W moim przypadku chciałem wyodrębnić plik z innej gałęzi do bieżącego katalogu roboczego, który był inny niż pierwotna lokalizacja pliku. Odpowiedź :

git show TREEISH:path/to/file >path/to/local/file

18
Zamiarem „git show” jest wyprowadzenie danych do terminala w czytelnym formacie, co nie gwarantuje dokładnego dopasowania zawartości pliku. Tak samo, jak lepiej jest skopiować dokument słowo jako całość, a nie próbować kopiować i wklejać jego treść do innego dokumentu.
Gonen

Chciałem tylko go wyświetlić, aby móc porównać zawartość z bieżącą gałęzią (sprawdź fragment kodu). Chciałbym jednak użyć vim z tym ... do podświetlania składni itp.
isaaclw

3
Aby porównać zawartość przed wykonaniem transakcji, git diff <other branch> <path to file>działa dobrze.
Randall

2
@ Gonen: Począwszy od gita w wersji 2.21.0, strona podręcznika „git show” mówi: „W przypadku zwykłych obiektów blob pokazuje zwykłą zawartość”. Nie jestem pewien, czy to oznacza, że ​​zawsze jesteśmy dobrzy. Jestem trochę ostrożny, aby pobrać zdjęcie w ten sposób ...
hibbelig

52

Co z użyciem polecenia kasy:

  git diff --stat "$branch"
  git checkout --merge "$branch" "$file"
  git diff --stat "$branch"

8
Uwaga Scalanie (2. polecenie) nie może działać, jeśli plik nie istnieje w obu gałęziach
simpleuser

Hm Nie mam diffstat. Czy to konkretna wersja narzędzia różnicowego, ponieważ nigdy o nim nie słyszałem (i powinienem na nią przejść?): D
dudewad

git diffobsługuje --statargument, który zasadniczo robi to samo co diffstat.
hlovdal

Musiałem mieć oba oddziały sprawdzone lokalnie, aby to zadziałało.
UnitasBrooks

18

1) Upewnij się, że jesteś w oddziale, w którym potrzebujesz kopii pliku. na przykład: chcę plik gałęzi sub w master, więc musisz przejść do kasy lub powinien być w mastergit checkout master

2) Teraz sprawdź sam konkretny plik, który chcesz z gałęzi sub w master,

git checkout sub_branch file_path/my_file.ext

tutaj sub_branchśrodki, gdzie masz ten plik, a następnie nazwę pliku trzeba skopiować.


Bardzo przydatny i dobrze wyjaśniony.
Abk

15

Po odpowiedzi madlepa możesz również skopiować jeden katalog z innego oddziału za pomocą obiektu blob katalogu.

git checkout other-branch app/**

Jeśli chodzi o pytanie op, jeśli zmieniłeś tylko jeden plik, będzie to działało dobrze ^ _ ^


1
Zauważ, że obie gałęzie należy odpowiednio wyciągnąć, najpierw lub użyć origin/other-branchw odniesieniu do gałęzi repo. Podstawy, ale mnie ugryzłeś. (odpowiedź jest świetna - nie wymaga edycji)
akauppi

8

Chciałbym użyć git restore(dostępny od gita 2.23)

git restore --source otherbranch path/to/myfile.txt


Dlaczego jest lepszy niż inne opcje?

git checkout otherbranch -- path/to/myfile.txt- Kopiuje plik do katalogu roboczego, ale także do obszaru przejściowego (podobny efekt, jakbyś skopiował ten plik ręcznie i wykonał git addna nim). git restorenie dotyka obszaru przeciwności (chyba że jest to zalecane przez --stagedopcję).

git show otherbranch:path/to/myfile.txt > path/to/myfile.txtużywa standardowego przekierowania powłoki. Jeśli używasz programu Powershell, może występować problem z kodowaniem tekstu lub możesz popsuć plik, jeśli jest on binarny . Ze git restorezmieniającymi plików odbywa się przez całygit wykonywalny.

Kolejną zaletą jest to, że możesz przywrócić cały folder za pomocą:

git restore --source otherbranch path/to

lub z, git restore --overlay --source otherbranch path/tojeśli chcesz uniknąć usuwania plików. Na przykład, jeśli jest mniej plików otherbranchniż w bieżącym katalogu roboczym (a pliki te są śledzone ) bez --overlayopcji git restorespowoduje ich usunięcie. Ale to jest dobre zachowanie domyślne, najprawdopodobniej chcesz, aby stan katalogu był taki sam jak w otherbranch, nie „taki sam, ale z dodatkowymi plikami w mojej bieżącej gałęzi”


Niezła odpowiedź. Czy istnieje git restoresposób na skopiowanie pliku z gałęzi źródłowej do nowego pliku w gałęzi docelowej? Z git show mogę to zrobić za pomocą przekierowania powłoki ( git show otherbranch:path/to/file1.txt > path/to/file2.txt), ale chcę uniknąć przekierowania powłoki z powodów, o których wspomniałeś.
AdmiralAdama

1
@AdmiralAdama nie bardzo. I myślę, że nie ma dużej szansy na to git restore(ale kto wie;)). Te problemy z przekierowaniem są w zasadzie problemem PowerShell, nie jestem pewien, czy jest jakaś inna powłoka, która ma z tym problem. Zwykle wracam do „git bash” lub nawet „cmd”, gdzie muszę użyć git showpoleceń „ z przekierowaniem”. Lub użyj GUI, takiego jak GitExtensions, w którym możesz przeglądać drzewo plików zatwierdzeń i kliknąć „Zapisz jako” na dowolnym pliku.
Mariusz Pawelski

O, rozumiem. Nie używam Powershell, więc być może przekierowanie powłoki jest dla mnie np. Dzięki za informację.
AdmiralAdama

3

Należy pamiętać, że w zaakceptowanej odpowiedzi pierwsza opcja zastępuje cały plik z drugiej gałęzi (npgit add ... zostało wykonane), a druga opcja powoduje po prostu skopiowanie pliku, ale nie wprowadza zmian (tak jakbyś miał właśnie edytowałem plik ręcznie i miałem wyjątkowe różnice).

Pobierz plik kopii z innej gałęzi bez przemieszczania go

Wprowadzone zmiany (np . git add filename):

$ git checkout directory/somefile.php feature-B

$ git status
On branch feature-A
Your branch is up-to-date with 'origin/feature-A'.
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

        modified:   directory/somefile.php

Zmiany nierozstrzygnięte (nie etapowe ani nie zatwierdzone):

$ git show feature-B:directory/somefile.php > directory/somefile.php

$ git status
On branch feature-A
Your branch is up-to-date with 'origin/feature-A'.
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

        modified:   directory/somefile.php

no changes added to commit (use "git add" and/or "git commit -a")

Pojawia się komunikat „funkcja-B nie jest plikiem”, nazwa gałęzi jest na pierwszym miejscu, o tym -> „> katalog / somefile.php” czy to może zmienić kodowanie pliku?
Tiago Oliveira de Freitas
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.