Jak scalić zmiany w jednym pliku zamiast scalać zatwierdzenia?

382

Mam dwie gałęzie (A i B) i chcę scalić pojedynczy plik z gałęzi A z odpowiednim pojedynczym plikiem z gałęzi B.

Isuru
źródło
2
Omówiono już tutaj stackoverflow.com/questions/449541/…
positron
27
Większość odpowiedzi na ten drugi post dotyczy selektywnego łączenia zatwierdzeń , a nie plików . To sprawia, że ​​wybrana odpowiedź jest niepoprawna. Pytanie pozostaje bez odpowiedzi.
Ta odpowiedź jest właściwą drogą, IMO. git diff branch_name > patch git apply patch. stackoverflow.com/a/9473543/1091853
blamb

Odpowiedzi:

630

Natknąłem się na ten sam problem. Mówiąc ściślej, mam dwie gałęzie Ai Bte same pliki, ale w niektórych plikach inny interfejs programowania. Teraz metody pliku f, które są niezależne od różnic interfejsu między dwiema gałęziami, zostały zmienione w gałęzi B, ale zmiana jest ważna dla obu gałęzi. Dlatego muszę połączyć tylko plik fgałęzi Bz plikiem fgałęzi A.

Proste polecenie już dla mnie rozwiązało problem, jeśli założę, że wszystkie zmiany zostały zatwierdzone w obu gałęziach Ai B:

git checkout A

git checkout --patch B f

Pierwsze polecenie zmienia się w gałąź A, w której chcę scalić Bwersję pliku f. Drugie polecenie patch plik fz fo HEADo B. Możesz nawet zaakceptować / odrzucić pojedyncze części łaty. Zamiast tego Bmożesz tutaj podać dowolny zatwierdzenie, nie musi to być HEAD.

Edycja społeczności : jeśli plik fna jeszcze Bnie istnieje A, pomiń --patchopcję. W przeciwnym razie otrzymasz komunikat „Bez zmian”. wiadomość.

loup
źródło
10
Działa to tylko wtedy, gdy chcesz zaktualizować plik. Co jeśli chcę dodać nowy plik z gałęzi B do gałęzi A?
Umair A.
25
@UmairAshraf powinieneś być w stanie dodać nowy plik z B do A, usuwając opcję --patch.
bbak
9
Hmmm ... kiedy próbuję, pojawia się komunikat „bez zmian”, ale wyraźnie są zmiany. OK, musiałem być w folderze, w którym znajdował się odpowiedni plik. Edycja: To może być prawdopodobnie moje ulubione rozwiązanie problemu, który widziałem podczas stackoverflow :-D
bot_bot
2
Musiałem użyć, git checkout --patch B -- fżeby to zadziałało.
user545424
8
Wystarczy dodać, że jeśli w pliku jest wiele zmian (skrawków) i chcesz je wszystkie wprowadzić , możesz naciskać aw fazie interaktywnej, zamiast naciskać za ykażdym razem. Lub git checkout B -- fzamiast tego użyj polecenia.
Dmitry Gonchar
17

Oto, co robię w tych sytuacjach. To kludge, ale dla mnie działa dobrze.

  1. Utwórz kolejny oddział na podstawie działającego oddziału.
  2. git pull / git scala wersję (SHA1), która zawiera plik, który chcesz skopiować. Spowoduje to scalenie wszystkich twoich zmian, ale używamy tej gałęzi tylko do pobrania jednego pliku.
  3. Napraw wszelkie konflikty itp. Zbadaj swój plik.
  4. sprawdź działający oddział
  5. Pobierz plik zatwierdzony podczas scalania.
  6. Zaangażuj się.

Próbowałem łatać i moja sytuacja była na to zbyt brzydka. Krótko mówiąc, wyglądałoby to tak:

Działająca gałąź: A Eksperymentalna gałąź: B (zawiera plik.txt, który zawiera zmiany, które chcę złożyć.)

git checkout A

Utwórz nowy oddział na podstawie A:

git checkout -b tempAB

Scal B w tempAB

git merge B

Skopiuj skrót sha1 scalenia:

git log

commit 8dad944210dfb901695975886737dc35614fa94e
Merge: ea3aec1 0f76e61
Author: matthewe <[email protected]>
Date:   Wed Oct 3 15:13:24 2012 -0700

Merge branch 'B' into tempAB

Sprawdź działający oddział:

git checkout A

Sprawdź swój naprawiony plik:

git checkout 7e65b5a52e5f8b1979d75dffbbe4f7ee7dad5017 file.txt

I powinieneś to mieć. Zaakceptuj swój wynik.

jaja
źródło
3
Więc musimy to wszystko zrobić, aby scalić jeden plik? Czy nie byłoby łatwiej skopiować i wkleić plik do drugiej gałęzi
Robin,
1
@ Robin prawdopodobnie nie, ponieważ scalanie zachowuje zmiany w pliku, które różnią się między gałęziami A i B. Kopiowanie pliku zastąpi wszelkie dodatkowe różnice między działającą gałęzią A a tym, co chciałbyś przynieść z B, które mogą nie zawierać te wpisy / zmiany. np. podejrzany Azmienił od Bpoczątku na inne sposoby. Kopiowanie zastąpi te różnice.
blamb
13

Wykorzystuje wewnętrzny difftool gita. Może trochę pracy do zrobienia, ale od razu.

#First checkout the branch you want to merge into
git checkout <branch_to_merge_into>

#Then checkout the file from the branch you want to merge from
git checkout <branch_to_merge_from> -- <file> 

#Then you have to unstage that file to be able to use difftool
git reset HEAD <file> 

#Now use difftool to chose which lines to keep. Click on the mergebutton in difftool
git difftool

#Save the file in difftool and you should be done.
Mikael Kellgren
źródło
1
Aby wyjaśnić użycie --(pustej etykiety argumentu), git checkout docs: ARGUMENT DISAMBIGUATION powiedz: „użyj, git checkout -- <pathspec>jeśli chcesz wyewidencjonować te ścieżki z indeksu”. Jest tak, ponieważ możesz mieć zarówno gałąź, jak i plik / ścieżkę o tej samej nazwie. W takich przypadkach, zamiast prosić o jednoznaczne ustalenie, czy gałąź lub ścieżka powinna zostać wypisana, gdy oba istnieją, git zdecyduje się na domyślną wypłatę gałęzi. Jednak jeśli --poprzedza, git zamiast tego pobierze plik / ścieżkę.
SherylHohman
8

Uznałem to podejście za proste i przydatne: jak „scalić” określone pliki z innej gałęzi

Jak się okazuje, staramy się zbyt mocno. Nasz dobry przyjaciel git Checkout jest właściwym narzędziem do pracy.

git checkout source_branch <paths>...

Możemy po prostu podać git checkout nazwę gałęzi funkcji A i ścieżki do określonych plików, które chcemy dodać do naszej gałęzi master.

Przeczytaj cały artykuł, aby uzyskać więcej zrozumienia

Paweł Cioch
źródło
2
To nadpisuje pliki, nie łączy ich
Alex G
Dla ciebie może to zależeć od tego, co robisz i co próbujesz osiągnąć. Chodzi o to, aby gałąź B była rozwidleniem A, modyfikujesz 4 pliki w B, ale chcesz scalić tylko 2 z B do A. Zwykłe scalanie scaliłoby wszystkie 4, tutaj możesz wybrać. Może to wyglądać tak, jakby zostały zastąpione, ponieważ B zawiera zasadniczo nowsze pliki. Musisz poprzeć swoje doświadczenie dowodami.
Paweł Cioch,
Zgadzam się, że to nadpisuje. myślę, że miałeś na myśli użycie -popcji w tym poleceniu. Które następnie nadpisują wszystkie części pliku roboczego, które wcześniej przekierowały z gałęzi, z której się wyewidencjonowałeś, przed zmianami łatki, niestety.
blamb
Pomysł był z 2009 roku, istnieje szansa, że ​​nowa wersja git zachowuje się inaczej i potrzebuje -p lub cokolwiek innego, ale z powrotem, kiedy go publikowałem, działało to dla mnie, ale znowu może nie obchodziło mnie, że pliki zostaną zastąpione, ponieważ najnowsza wersja była tym, czego potrzebowałem
Paweł Cioch
3

Następujące polecenie (1) porówna plik prawidłowej gałęzi, aby master (2) interaktywnie zapytał, jakie modyfikacje zastosować.

git checkout --patch master

użytkownik1854182
źródło
0

Moja edycja została odrzucona, więc tutaj dołączam, jak obsługiwać scalanie zmian ze zdalnego oddziału.

Jeśli musisz to zrobić po niepoprawnym scaleniu, możesz zrobić coś takiego:

# If you did a git pull and it broke something, do this first
# Find the one before the merge, copy the SHA1
git reflog
git reset --hard <sha1>

# Get remote updates but DONT auto merge it
git fetch github 

# Checkout to your mainline so your branch is correct.
git checkout develop 

# Make a new branch where you'll be applying matches
git checkout -b manual-merge-github-develop

# Apply your patches
git checkout --patch github/develop path/to/file
...

# Merge changes back in
git checkout develop
git merge manual-merge-github-develop # optionally add --no-ff

# You'll probably have to
git push -f # make sure you know what you're doing.
zupa
źródło
0

Zakładając, że B jest bieżącą gałęzią:

$ git diff A <file-path> > patch.tmp
$ git apply patch.tmp -R

Pamiętaj, że dotyczy to tylko zmian w pliku lokalnym. Musisz później dokonać zobowiązania.

jbirkel
źródło
Dla mnie generuje toerror: <file-path>: already exists in working directory
kontur
Powinieneś podać konkretny plik lub ścieżkę pliku w bieżącym katalogu. Używamgit diff Branch_A <file-path, filename> -- hash_commit > file_name.temp
R.Chatsiri
0

Możesz pobrać starą wersję pliku do scalenia, zapisując go pod inną nazwą, a następnie uruchomić dowolne narzędzie do scalania na dwóch plikach.

na przykład.

git show B:src/common/store.ts > /tmp/store.ts (gdzie B jest nazwą oddziału / zatwierdzenia / znacznika)

meld src/common/store.ts /tmp/store.ts

Salami
źródło
0

Zrobię to jak

git format-patch branch_old..branch_new file

spowoduje to utworzenie poprawki do pliku.

Zastosuj łatkę w miejscu docelowym branch_old

git am blahblah.patch

Nowicjusz
źródło
Czy możesz z łatwością zajrzeć do plastra, aby uzyskać dodatkowe bezpieczeństwo?
XavierStuvw