Jak mogę selektywnie scalić lub wybrać zmiany z innej gałęzi w Git?

Używam Gita w nowym projekcie, który ma dwie równoległe, ale obecnie eksperymentalne gałęzie rozwoju:

  • master: import istniejącej bazy kodowej plus kilka modyfikacji, których generalnie jestem pewien
  • exp1: Oddział doświadczalny #1
  • exp2: Oddział doświadczalny # 2

exp1 i exp2 reprezentują dwa bardzo różne podejścia architektoniczne. Dopóki nie przejdę dalej, Nie wiem, który z nich (jeśli któryś z nich) zadziała. Gdy robię postępy w jednej gałęzi, czasami mam edycje, które przydałyby się w drugiej gałęzi i chciałbym połączyć tylko te.

Jaki jest najlepszy sposób łączenia selektywnych zmian z jednej gałęzi rozwoju do drugiej, pozostawiając wszystko inne?

Podejścia, które rozważałem:

  1. git merge --no-commit następnie ręczne Odinstalowywanie dużej liczby edycji, których nie chcę robić wspólnie między gałęziami.

  2. Instrukcja kopiowanie plików wspólnych do katalogu tymczasowego, a następnie git checkout, aby przejść do innej gałęzi, a następnie więcej ręcznego kopiowania z katalogu tymczasowego do drzewa roboczego.

  3. Wariacja na temat powyższego. Porzuć na razie gałęzie exp i użyj dwóch dodatkowych lokalnych repozytoriów do eksperymentów. Dzięki temu ręczne kopiowanie plików jest znacznie prostsze.

Wszystkie trzy z tych podejść wydają się żmudne i podatne na błędy. Mam nadzieję, że tam jest lepszym podejściem; coś podobnego do parametru ścieżki filtra, który uczyniłby git-merge bardziej selektywnym.
Author: Peter Mortensen, 2009-01-16

25 answers

Używasz cherry-pick aby uzyskać indywidualne commity z jednej gałęzi.

Jeśli zmiany, które chcesz zmienić, nie znajdują się w poszczególnych commitach, użyj metody pokazanej tutaj, aby podzielić commity na poszczególne commity. Ogólnie rzecz biorąc, używasz git rebase -i, aby uzyskać oryginalny commit do edycji, następnie git reset HEAD^, aby selektywnie cofnąć zmiany, a następnie git commit zatwierdzić Ten bit jako nowy commit w historii.

Jest jeszcze jedna fajna metoda w magazynie Red Hat, gdzie używają git add --patch lub ewentualnie git add --interactive, co pozwala na dodawanie tylko części kawałka, jeśli chcesz podzielić różne zmiany do pojedynczego pliku (wyszukaj na tej stronie "podziel").

Po podzieleniu zmian, możesz teraz wybrać tylko te, które chcesz.

 500
Author: 1800 INFORMATION,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-05-01 01:40:07

Miałem dokładnie ten sam problem, o którym wspomniałeś powyżej. Ale znalazłem to jaśniejsze w wyjaśnieniu odpowiedzi.

Podsumowanie:

  • Sprawdź ścieżkę(ścieżki) z gałęzi, którą chcesz połączyć,

     $ git checkout source_branch -- <paths>...
    
    Hint: It also works without `--` like seen in the linked post.
    
  • Lub do selektywnego łączenia hunksów

     $ git checkout -p source_branch -- <paths>...
    

Alternatywnie użyj reset, a następnie dodaj z opcją -p,

    $ git reset <paths>...
    $ git add -p <paths>...
  • Wreszcie commit

     $ git commit -m "'Merge' these changes"
    
 1020
Author: Chris Steinbach,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-07-28 11:08:26

Aby selektywnie scalić pliki z jednej gałęzi do drugiej, Uruchom

git merge --no-ff --no-commit branchX

Gdzie branchX jest gałęzią, z której chcesz połączyć się z bieżącą gałęzią.

Opcja --no-commit będzie wystawiać pliki, które zostały połączone przez Git bez konieczności ich zatwierdzania. Daje to możliwość modyfikowania scalonych plików w dowolny sposób, a następnie zatwierdzania ich samodzielnie.

W zależności od tego, jak chcesz scalić pliki, istnieją cztery przypadki:

1) ty chcę prawdziwego połączenia.

W tym przypadku, akceptujesz scalone pliki tak, jak Git połączył je automatycznie, a następnie zatwierdzasz je.

2) są pliki, których nie chcesz połączyć.

Na przykład, chcesz zachować wersję w bieżącej gałęzi i zignorować wersję w gałęzi, z której się łączysz.

Aby wybrać wersję w bieżącej gałęzi, Uruchom:

git checkout HEAD file1

To pobierze wersję file1 w bieżącej gałęzi i nadpisze file1 automerged by Git.

3) Jeśli chcesz mieć wersję w branchX (a nie True merge).

Run:

git checkout branchX file1

To pobierze wersję file1 W branchX i nadpisze file1 automatycznie scalone przez Git.

4) ostatni przypadek jest, jeśli chcesz wybrać tylko konkretne połączenia w file1.

W tym przypadku możesz edytować zmodyfikowaną file1 bezpośrednio, zaktualizować ją do dowolnej wersji file1, a następnie zatwierdzić.

Jeśli Git nie może Scal plik automatycznie, zgłosi plik jako " unmerged " i wygeneruje kopię, w której będziesz musiał ręcznie rozwiązać konflikty.



Aby wyjaśnić dalej za pomocą przykładu, załóżmy, że chcesz połączyć branchX z bieżącą gałęzią:

git merge --no-ff --no-commit branchX

Następnie uruchom polecenie git status, aby wyświetlić status zmodyfikowanych plików.

Na przykład:

git status

# On branch master
# Changes to be committed:
#
#       modified:   file1
#       modified:   file2
#       modified:   file3
# Unmerged paths:
#   (use "git add/rm <file>..." as appropriate to mark resolution)
#
#       both modified:      file4
#

Gdzie file1, file2, i {[22] } są plikami, które git pomyślnie automatyczne scalanie.

Oznacza to, że zmiany w master i branchX dla wszystkich tych trzech plików zostały połączone razem bez żadnych konfliktów.

Możesz sprawdzić, jak połączenie zostało wykonane, uruchamiając git diff --cached;

git diff --cached file1
git diff --cached file2
git diff --cached file3

Jeśli okaże się, że połączenie jest niepożądane, możesz

  1. edycja pliku bezpośrednio
  2. Zapisz
  3. git commit

Jeśli nie chcesz połączyć file1 i chcesz zachować wersję w bieżącym oddział

Run

git checkout HEAD file1

Jeśli nie chcesz łączyć file2 i chcesz tylko wersję w branchX

Run

git checkout branchX file2

Jeśli chcesz, aby file3 były połączone automatycznie, nie rób nic.

Git już to połączył.


file4 powyżej znajduje się nieudane scalanie przez Git. Oznacza to, że zmiany w obu gałęziach zachodzą na tej samej linii. W tym miejscu należy ręcznie rozwiązać konflikty. Można usunąć scalanie odbywa się poprzez edycję pliku bezpośrednio lub uruchomienie polecenia checkout dla wersji w gałęzi, którą chcesz się stać file4.


Wreszcie, nie zapomnij git commit.

 367
Author: alvinabad,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-07-28 09:52:36

Nie podoba mi się powyższe podejście. Korzystanie z cherry-pick jest Świetne do wybrania jednej zmiany, ale jest to ból, jeśli chcesz wprowadzić wszystkie zmiany z wyjątkiem niektórych złych. Oto moje podejście.

Nie ma --interactive argumentu, który możesz przekazać do git merge.

Oto alternatywa:

Masz pewne zmiany w gałęzi 'feature' I chcesz przenieść niektóre, ale nie wszystkie z nich do 'master' w niezbyt niechlujny sposób (tzn. nie chcesz wybierać i zatwierdzać każdej z nich one)

git checkout feature
git checkout -b temp
git rebase -i master

# Above will drop you in an editor and pick the changes you want ala:
pick 7266df7 First change
pick 1b3f7df Another change
pick 5bbf56f Last change

# Rebase b44c147..5bbf56f onto b44c147
#
# Commands:
# pick = use commit
# edit = use commit, but stop for amending
# squash = use commit, but meld into previous commit
#
# If you remove a line here THAT COMMIT WILL BE LOST.
# However, if you remove everything, the rebase will be aborted.
#

git checkout master
git pull . temp
git branch -d temp

Więc po prostu zawiń to w skrypcie powłoki, Zmień master na $to i zmień feature na $from i gotowe:

#!/bin/bash
# git-interactive-merge
from=$1
to=$2
git checkout $from
git checkout -b ${from}_tmp
git rebase -i $to
# Above will drop you in an editor and pick the changes you want
git checkout $to
git pull . ${from}_tmp
git branch -d ${from}_tmp
 110
Author: nosatalian,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-02-22 22:54:54

Jest inny sposób:

git checkout -p
Jest to mieszanka pomiędzy git checkout i git add -p i może być dokładnie tym, czego szukasz:
   -p, --patch
       Interactively select hunks in the difference between the <tree-ish>
       (or the index, if unspecified) and the working tree. The chosen
       hunks are then applied in reverse to the working tree (and if a
       <tree-ish> was specified, the index).

       This means that you can use git checkout -p to selectively discard
       edits from your current working tree. See the “Interactive Mode”
       section of git-add(1) to learn how to operate the --patch mode.
 96
Author: Chronial,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-07-14 07:54:53

Chociaż niektóre z tych Odpowiedzi są całkiem dobre, czuję, że żadna nie odpowiedziała na pierwotne ograniczenie OP: wybieranie poszczególnych plików z poszczególnych gałęzi. To rozwiązanie to robi, ale może być żmudne, jeśli jest wiele plików.

Powiedzmy, że masz master, exp1, i exp2 gałęzie. Chcesz połączyć jeden plik z każdej gałęzi eksperymentalnej w master. Zrobiłbym coś takiego:

git checkout master
git checkout exp1 path/to/file_a
git checkout exp2 path/to/file_b

# Save these files as a stash
git stash

# Merge stash with master
git merge stash

To da ci w pliku diffs dla każdego z plików, które chcę. Nic więcej. Nie mniej. Warto mieć radykalnie różne zmiany plików pomiędzy wersjami-w moim przypadku zmiana aplikacji z Ruby on Rails 2 Na Ruby on Rails 3.

Spowoduje scalenie plików, ale spowoduje inteligentne scalanie. Nie byłem w stanie dowiedzieć się, jak użyć tej metody, aby uzyskać informacje o różnicach w pliku (może nadal będzie to dla ekstremalnych różnic. Irytujące małe rzeczy, takie jak białe znaki, są ponownie scalane, chyba że użyjesz opcji -s recursive -X ignore-all-space)

 59
Author: Eric Hu,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-07-28 11:15:04

1800 odpowiedź Informacji jest całkowicie poprawna. Jako ktoś nowy w Git, jednak "użyj git cherry-pick" nie wystarczyło mi, aby to rozgryźć bez większego kopania w Internecie, więc pomyślałem, że opublikuję bardziej szczegółowy przewodnik na wypadek, gdyby ktoś inny był w podobnej łodzi.

Moim przypadkiem użycia była chęć selektywnego ściągnięcia zmian z czyjejś gałęzi GitHub do mojej własnej. Jeśli masz już lokalny oddział ze zmianami, wystarczy wykonać kroki 2 i 5-7.

  1. Utwórz (jeśli nie utworzono) lokalną gałąź ze zmianami, które chcesz wprowadzić.

    $ git branch mybranch <base branch>

  2. Przełącz się.

    $ git checkout mybranch

  3. Usuń zmiany, które chcesz z konta drugiej osoby. Jeśli jeszcze tego nie zrobiłeś, będziesz chciał dodać je jako pilota.

    $ git remote add repos-w-changes <git url>

  4. Ściągnij wszystko z ich gałęzi.

    $ git pull repos-w-changes branch-i-want

  5. Wyświetl dzienniki zmian, aby zobaczyć, które zmiany chcesz:

    $ git log

  6. Wróć do gałęzi, do której chcesz wprowadzić zmiany.

    $ git checkout originalbranch

  7. Cherry wybierz swoje commity, jeden po drugim, z hashami.

    $ git cherry-pick -x hash-of-commit

 52
Author: Cory,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-07-29 12:09:02

Oto jak możesz zamienić Myclass.java plik w gałęzi master na Myclass.java w gałęzi feature1. Będzie działać nawet jeśli Myclass.java nie istnieje na master.

git checkout master
git checkout feature1 Myclass.java

UWAGA To nadpisze-nie Scali - i raczej zignoruje lokalne zmiany w gałęzi master.

 41
Author: maestr0,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-10-19 02:24:30

Prosty sposób, aby faktycznie scalić określone pliki z dwóch gałęzi, a nie tylko zastąpić określone pliki z innej gałęzi.

Krok pierwszy: rozróżnienie gałęzi

git diff branch_b > my_patch_file.patch

Tworzy plik z łatą różnicy pomiędzy bieżącą gałęzią a gałęzią_b

Krok drugi: nałóż łatkę na pliki pasujące do wzorca

git apply -p1 --include=pattern/matching/the/path/to/file/or/folder my_patch_file.patch

Przydatne uwagi na temat opcji

Możesz użyć * jako wieloznaczności we wzorze include.

Ścinki nie musisz uciekać.

Możesz również użyć opcji -- exclude i zastosować ją do wszystkich plików, z wyjątkiem plików pasujących do wzorca, lub odwrócić łatkę za pomocą opcji-R

Opcja-p1 jest przechowywana z polecenia * Unix patch i fakt, że zawartość pliku z łatą przed każdą nazwą pliku zawiera a/ lub b/ (lub więcej w zależności od tego, jak Plik z łatą został wygenerowany), który należy usunąć, aby mógł on określić prawdziwy plik do ścieżki do pliku, który ma być zastosowany za.

Sprawdź stronę podręcznika Git-apply, aby uzyskać więcej opcji.

Krok trzeci: nie ma kroku trzeciego

Oczywiście chciałbyś zatwierdzić swoje zmiany, ale kto powie, że nie masz innych powiązanych poprawek, które chcesz zrobić przed zatwierdzeniem.

 29
Author: masukomi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-07-28 11:19:50

Oto jak możesz sprawić, aby Historia śledziła tylko kilka plików z innej gałęzi bez większego zamieszania, nawet jeśli bardziej "proste" scalenie przyniosłoby o wiele więcej zmian, których nie chcesz.

Po pierwsze, wykonasz nietypowy krok i zadeklarujesz z góry, że to, co zamierzasz zatwierdzić, jest połączeniem, bez konieczności robienia przez Git czegokolwiek z plikami w Twoim katalogu roboczym:

git merge --no-ff --no-commit -s ours branchname1

... gdzie "branchname" jest tym, co twierdzisz, że się łączysz. Gdybyś commit od razu nie wprowadzałby żadnych zmian, ale nadal pokazywałby pochodzenie z drugiej gałęzi. Możesz dodać więcej gałęzi, znaczników itp. w razie potrzeby również do linii poleceń. W tym momencie jednak, nie ma żadnych zmian do zatwierdzenia, więc pobierz pliki z innych wersji, Następny.

git checkout branchname1 -- file1 file2 etc.

Jeśli łączyłeś się z więcej niż jednej gałęzi, powtarzaj w razie potrzeby.

git checkout branchname2 -- file3 file4 etc.

Teraz pliki z drugiej gałęzi są w indeksie, gotowe do zatwierdzenia, z historia.

git commit

I będziesz miał wiele do wyjaśnienia w tej wiadomości commit.

Proszę jednak pamiętać, na wypadek, gdyby nie było jasne, że jest to pokręcona rzecz do zrobienia. Nie jest to w duchu tego, do czego służy "gałąź" , a cherry-pick jest bardziej uczciwym sposobem na to, co robisz, tutaj. Jeśli chcesz wykonać kolejne "scalanie" dla innych plików z tej samej gałęzi, których nie przyniosłeś ostatnim razem, zatrzyma cię to Komunikatem "już aktualne". To objaw nie rozgałęzienie, kiedy powinniśmy mieć, w tym, że gałąź "od" powinna być więcej niż jedna inna gałąź.

 25
Author: jejese,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-07-28 11:24:36

Znalazłem ten post zawiera najprostszą odpowiedź. Tylko do:

git checkout <branch from which you want files> <file paths>

Przykład

Ciągnę .plik gitignore z branchB do bieżącej gałęzi:
git checkout branchB .gitignore
Więcej informacji można znaleźć w poście.
 15
Author: Stunner,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-07-28 11:36:49

To jest mój obieg pracy do scalania plików selektywnych.

# Make a new branch (this will be temporary)
git checkout -b newbranch

# Grab the changes
git merge --no-commit  featurebranch

# Unstage those changes
git reset HEAD
(You can now see the files from the merge are unstaged)

# Now you can chose which files are to be merged.
git add -p

# Remember to "git add" any new files you wish to keep
git commit
 15
Author: Felix,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-07-28 11:37:49

Najprostszym sposobem jest ustawienie repozytorium na gałąź, z którą chcesz się połączyć, a następnie uruchomienie

git checkout [branch with file] [path to file you would like to merge]

If you run

git status

Zobaczysz plik już wystawiony...

Następnie uruchom

git commit -m "Merge changes on '[branch]' to [file]"
Proste.
 15
Author: dsieczko,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-07-28 11:38:52

To dziwne, że git nadal nie ma tak wygodnego narzędzia "po wyjęciu z pudełka". Używam go mocno podczas aktualizacji starej gałęzi wersji (która wciąż ma wielu użytkowników Oprogramowania) przez tylko kilka poprawek z bieżącej gałęzi wersji. W tym przypadku często potrzebne jest szybkie pobranie tylko niektórych linii kodu z pliku w bagażniku, ignorując wiele innych zmian (które nie powinny wejść do starej wersji)... I oczywiście interaktywne trójdrożne scalanie jest potrzebne w tym przypadku, git checkout --patch <branch> <file path> nie nadaje się do tego selektywnego scalania.

Możesz to zrobić łatwo:

Wystarczy dodać tę linię do [alias] sekcji w pliku global .gitconfig lub local .git/config:

[alias]
    mergetool-file = "!sh -c 'git show $1:$2 > $2.theirs; git show $(git merge-base $1 $(git rev-parse HEAD)):$2 > $2.base; /C/BCompare3/BCompare.exe $2.theirs $2 $2.base $2; rm -f $2.theirs; rm -f $2.base;' -"

To oznacza, że używasz Beyond Compare. W razie potrzeby wystarczy przejść na oprogramowanie do wyboru. Możesz też zmienić go na trójdrożne automatyczne scalanie, jeśli nie potrzebujesz interaktywnego selektywnego scalania:

[alias]
    mergetool-file = "!sh -c 'git show $1:$2 > $2.theirs; git show $(git merge-base $1 $(git rev-parse HEAD)):$2 > $2.base; git merge-file $2 $2.base $2.theirs; rm -f $2.theirs; rm -f $2.base;' -"

Następnie użyj tak:

git mergetool-file <source branch> <file path>

To da Ci prawdziwą selektywną tree-way możliwość scalania dowolnego pliku w innej gałęzi.

 13
Author: JimStar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2021-02-08 19:01:48

To nie jest dokładnie to, czego szukałeś, ale było dla mnie przydatne:

git checkout -p <branch> -- <paths> ...
Jest to mieszanka kilku odpowiedzi.
 10
Author: Felipe,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-02-09 01:14:28

Miałem dokładnie ten sam problem, o którym wspomniałeś powyżej. Ale znalazłem Ten blog Gita jaśniejszy w wyjaśnieniu odpowiedzi.

Polecenie z powyższego linku:

# You are in the branch you want to merge to
git checkout <branch_you_want_to_merge_from> <file_paths...>
 10
Author: Susheel Javadi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-07-28 11:42:59

Zrobiłbym

Git diff commit 1..commit 2 filepattern / git-apply --index & & git commit

W ten sposób możesz ograniczyć zakres commitów dla pattern plików z gałęzi.

Jest kradziony z Re: jak ściągnąć tylko kilka plików z jednej gałęzi do drugiej?

 8
Author: lumpidu,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-07-28 11:43:51

Dla mnie, {[0] } jest najprostszym sposobem selektywnego wybierania zmian z innej gałęzi, ponieważ to polecenie umieszcza w moim drzewie roboczym wszystkie zmiany różnic, i mogę łatwo wybrać lub przywrócić, który z nich jest mi potrzebny.

W ten sposób mam pełną kontrolę nad zatwierdzonymi plikami.
 7
Author: GarryOne,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-06-12 22:55:37

Podoba mi się poprzednia 'Git-interactive-merge' odpowiedź, ale jest jedna łatwiejsza. Niech Git zrobi to za ciebie używając kombinacji rebase interactive i onto:

      A---C1---o---C2---o---o feature
     /
----o---o---o---o master

Więc chodzi o to, że chcesz C1 i C2 z gałęzi ' feature '(gałąź' a'), ale na razie nie ma reszty.

# git branch temp feature
# git checkout master
# git rebase -i --onto HEAD A temp

Który, tak jak w poprzedniej odpowiedzi, wrzuca Cię do edytora interaktywnego, gdzie zaznaczasz linie "wybierz" dla C1 i C2 (jak wyżej). Zapisać i zamknąć, a następnie będzie kontynuować z rebase i daje Ci gałąź 'temp', a także HEAD NA master + C1 + C2:

      A---C1---o---C2---o---o feature
     /
----o---o---o---o-master--C1---C2 [HEAD, temp]

Wtedy możesz po prostu zaktualizować master do HEAD i usunąć gałąź temp i możesz iść:

# git branch -f master HEAD
# git branch -d temp
 7
Author: Wade,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-08-02 03:08:09

Napisałem własny skrypt o nazwie 'pmerge' do częściowego scalania katalogów. Jest to praca w toku i nadal uczę się zarówno skryptów Git i Bash.

To polecenie używa git merge --no-commit, a następnie odrzuca zmiany, które nie pasują do podanej ścieżki.

Użycie: git pmerge branch path
Przykład: git merge develop src/

Nie testowałem go zbyt intensywnie. Katalog roboczy powinien być wolny od niezakontraktowanych zmian i nie śledzonych plików.
#!/bin/bash

E_BADARGS=65

if [ $# -ne 2 ]
then
    echo "Usage: `basename $0` branch path"
    exit $E_BADARGS
fi

git merge $1 --no-commit
IFS=$'\n'

# List of changes due to merge | replace nulls with newlines | strip lines to just filenames | ensure lines are unique
for f in $(git status --porcelain -z -uno | tr '\000' '\n' | sed -e 's/^[[:graph:]][[:space:]]\{1,\}//' | uniq); do
    [[ $f == $2* ]] && continue
    if git reset $f >/dev/null 2>&1; then
        # Reset failed... file was previously unversioned
        echo Deleting $f
        rm $f
    else
        echo Reverting $f
        git checkout -- $f >/dev/null 2>&1
    fi
done
unset IFS
 6
Author: Andy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-07-28 12:36:32

Możesz użyć read-tree, Aby odczytać lub połączyć dane zdalne drzewo z bieżącym indeksem, na przykład:

git remote add foo [email protected]/foo.git
git fetch foo
git read-tree --prefix=my-folder/ -u foo/master:trunk/their-folder

Aby wykonać połączenie, użyj -m.

[[3]}Zobacz: jak scalić podkatalog w Git?
 5
Author: kenorb,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-07-28 12:49:29

Proste podejście do selektywnego łączenia / zatwierdzania przez plik:

git checkout dstBranch
git merge srcBranch

// Make changes, including resolving conflicts to single files
git add singleFile1 singleFile2
git commit -m "message specific to a few files"
git reset --hard # Blow away uncommitted changes
 4
Author: Dave C,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-07-28 12:50:47

Jeśli nie masz zbyt wielu plików, które się zmieniły, nie będziesz miał żadnych dodatkowych commitów.

1. Duplicate branch
$ git checkout -b temp_branch

2. Reset do ostatniego wanted commit
$ git reset --hard HEAD~n, Gdzie n jest liczbą commitów, które musisz cofnąć

3. Sprawdź każdy plik z oryginalnej gałęzi
$ git checkout origin/original_branch filename.ext

Teraz możesz zatwierdzić i wymusić push (aby zastąpić zdalnego), jeśli zajdzie taka potrzeba.

 3
Author: JBaczuk,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-10-16 18:15:48

Jeśli potrzebujesz tylko połączyć konkretny katalog i pozostawić wszystko inne nienaruszone, a jednocześnie zachować historię, Możesz spróbować tego... Utwórz nową target-branch z master przed eksperymentem.

Poniższe kroki zakładają, że masz dwie gałęzie target-branch i source-branch, A katalog dir-to-merge, który chcesz połączyć, znajduje się w source-branch. Załóżmy również, że masz inne katalogi, takie jak dir-to-retain w celu, że nie chcesz zmieniać i zachować historii. Ponadto zakłada się, że istnieją konflikty scalające w dir-to-merge.

git checkout target-branch
git merge --no-ff --no-commit -X theirs source-branch
# the option "-X theirs", will pick theirs when there is a conflict. 
# the options "--no--ff --no-commit" prevent a commit after a merge, and give you an opportunity to fix other directories you want to retain, before you commit this merge.

# the above, would have messed up the other directories that you want to retain.
# so you need to reset them for every directory that you want to retain.
git reset HEAD dir-to-retain
# verify everything and commit.
 3
Author: code4kix,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-11-06 16:35:35

Gdy tylko kilka plików zmieniło się pomiędzy aktualnymi zatwierdzeniami dwóch gałęzi, ręcznie scalam zmiany, przeglądając różne pliki.

git difftool <branch-1>..<branch-2>

Zobacz https://sites.google.com/site/icusite/setup/git-difftool

 2
Author: raratiru,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-10-14 19:47:56