872 Stimmen

Wie kann man mit git-cherry-pick nur Änderungen an bestimmten Dateien vornehmen?

Wenn ich in einem Git-Zweig die Änderungen zusammenführen möchte, die nur an einigen der Dateien vorgenommen wurden, die in einem bestimmten Commit geändert wurden, der Änderungen an mehreren Dateien enthält, wie kann dies erreicht werden?

Angenommen, der Git-Commit namens stuff hat Änderungen an Dateien A , B , C y D aber ich möchte nur zusammenführen stuff Änderungen an Dateien A y B . Das klingt wie ein Job für git cherry-pick sondern cherry-pick weiß nur, wie man ganze Commits zusammenführt, nicht eine Teilmenge der Dateien.

988voto

Cascabel Punkte 449595

Ich würde es tun mit cherry-pick -n ( --no-commit ), mit dem Sie das Ergebnis vor dem Übertragen prüfen (und ändern) können:

git cherry-pick -n <commit>

# unstage modifications you don't want to keep, and remove the
# modifications from the work tree as well.
# this does work recursively!
git checkout HEAD <path>

# commit; the message will have been stored for you by cherry-pick
git commit

Wenn es sich bei den meisten Änderungen um Dinge handelt, die Sie nicht wollen, können Sie, anstatt die einzelnen Pfade zu überprüfen (der mittlere Schritt), alles zurücksetzen und dann das Gewünschte hinzufügen:

# unstage everything
git reset HEAD

# stage the modifications you do want
git add <path>

# make the work tree match the index
# (do this from the top level of the repo)
git checkout .

25 Stimmen

Zusätzlich zu git checkout . Ich würde auch empfehlen git clean -f um alle neuen, aber unerwünschten Dateien zu entfernen, die durch den "Cherry-Picked-Commit" eingeführt wurden.

7 Stimmen

Zusätzlicher Hinweis für die letztgenannte Methode: Ich verwende git add -p mit der Sie interaktiv entscheiden können, welche Änderungen Sie in den Index aufnehmen wollen pro Datei

7 Stimmen

Das ist nicht so toll für den Fall, dass der ausgewählte Commit nicht auf die aktuelle Arbeitskopie zutrifft, weil sie so anders ist, sondern dass eine Datei würde sauber auftragen.

270voto

Michael Anderson Punkte 65535

Die anderen Methoden haben bei mir nicht funktioniert, da die Übertragung viele Änderungen und Konflikte mit vielen anderen Dateien enthielt. Was ich mir ausgedacht habe, war einfach

git show SHA -- file1.txt file2.txt | git apply -

Es ist nicht wirklich add die Dateien oder führen eine Übergabe für Sie durch, so dass Sie möglicherweise mit

git add file1.txt file2.txt
git commit -c SHA

Wenn Sie das Hinzufügen überspringen möchten, können Sie auch die Option --cached Argument zu git apply

git show SHA -- file1.txt file2.txt | git apply --cached -

Das Gleiche können Sie auch für ganze Verzeichnisse tun

git show SHA -- dir1 dir2 | git apply -

3 Stimmen

Interessante Methode, danke. Aber tut nicht show SHA -- file | apply tun im Grunde das Gleiche wie checkout SHA -- file wie in Mark Longair's Antwort ?

11 Stimmen

Nö, checkout SHA -- file wird genau die Version bei SHA auschecken, während show SHA -- file | apply wendet nur die Änderungen in SHA an (genau wie cherry-pick). Es spielt eine Rolle, ob (a) es mehr als einen Commit gibt, der die angegebene Datei im Quellzweig ändert, oder (b) es einen Commit gibt, der die Datei in Ihrem aktuellen Zielzweig ändert.

0 Stimmen

Einfach, präzise und schön - das ist die beste Antwort. Genau das, wonach ich gesucht habe :-)

177voto

Tyrone Wilson Punkte 3800

Ich verwende normalerweise die -p Flagge mit einem Git-Checkout aus dem anderen Zweig, was ich einfacher und detaillierter finde als die meisten anderen Methoden, die ich kenne.

Im Prinzip:

git checkout <other_branch_name> <files/to/grab in/list/separated/by/spaces> -p

Beispiel:

git checkout mybranch config/important.yml app/models/important.rb -p

Sie erhalten dann ein Dialogfeld, in dem Sie gefragt werden, welche Änderungen Sie in "Blobs" haben möchten, was so ziemlich jede kontinuierliche Codeänderung ausmacht, die Sie dann signalisieren können y (Ja) n (Nein) usw. für jedes Stückchen Code.

El -p o patch Option funktioniert für eine Vielzahl von Befehlen in Git, darunter git stash save -p mit der Sie auswählen können, was Sie von Ihrer aktuellen Arbeit aufbewahren möchten

Ich verwende diese Technik manchmal, wenn ich eine Menge Arbeit erledigt habe und diese in themenbezogene Commits aufteilen möchte, indem ich git add -p und wähle aus, was ich für jede Übergabe möchte :)

5 Stimmen

Ich verwende regelmäßig git-add -p aber ich wusste es nicht git-checkout hat auch eine -p Flagge - behebt dies die Probleme beim Zusammenführen die Nicht -p Antwort hat?

0 Stimmen

@TobiasKienzler, ich denke schon, wenn Sie keine Zeilen auswählen, die zu Konflikten führen, aber es gäbe immer noch Code zu entwirren, wenn Ihre Datei zu sehr verändert wurde.

1 Stimmen

Mindestens -p würde eine manuelle Bearbeitung eines solchen widersprüchlichen Abschnitts ermöglichen, was cherry-pick würde wahrscheinlich auch so nachgeben. Ich werde das nächste Mal, wenn ich es brauche, testen, auf jeden Fall ein interessanter Ansatz

62voto

techdreams Punkte 4903

Die Situation:

Sie befinden sich in Ihrer Filiale, sagen wir mal master und Sie haben Ihren Commit auf einem beliebigen anderen Zweig. Sie müssen nur eine Datei aus diesem bestimmten Commit auswählen.

Der Ansatz:

Schritt 1: Bezahlen Sie in der gewünschten Filiale.

git checkout master

Schritt 2: Stellen Sie sicher, dass Sie den erforderlichen Commit-Hash kopiert haben.

git checkout commit_hash path\to\file

Schritt 3: Sie haben nun die Änderungen der gewünschten Datei in Ihrem gewünschten Zweig. Sie müssen sie nur noch hinzufügen und übertragen.

git add path\to\file
git commit -m "Your commit message"

2 Stimmen

Unglaublich! Funktioniert auch für alle Änderungen in einem Verzeichnis mit \path\to\directory\ für mich

2 Stimmen

Ich danke Ihnen vielmals! Das ist viel einfacher als Kirschenpflücken

3 Stimmen

Überschreibt alle am Zielzweig vorgenommenen Änderungen.

53voto

Mark Longair Punkte 412179

Vielleicht ist der Vorteil dieser Methode gegenüber Jefromi's Antwort ist, dass man sich nicht merken muss, welches Verhalten der Git-Reset ist der richtige :)

 # Create a branch to throw away, on which we'll do the cherry-pick:
 git checkout -b to-discard

 # Do the cherry-pick:
 git cherry-pick stuff

 # Switch back to the branch you were previously on:
 git checkout -

 # Update the working tree and the index with the versions of A and B
 # from the to-discard branch:
 git checkout to-discard -- A B

 # Commit those changes:
 git commit -m "Cherry-picked changes to A and B from [stuff]"

 # Delete the temporary branch:
 git branch -D to-discard

3 Stimmen

Danke für Ihre Antwort. Das hat mich jetzt zum Nachdenken angeregt, warum nicht die cherry-pick und direkt verwenden git checkout stuff -- A B ? Und mit git commit -C stuff die Übergabemeldung würde ebenfalls gleich bleiben

12 Stimmen

@Tobias: Das würde nur funktionieren, wenn die Dateien, die am stuff weder in Ihrem aktuellen Zweig noch irgendwo zwischen dem gemeinsamen Vorfahren von HEAD y stuff und die Spitze des stuff . Wenn sie das haben, dann cherry-pick erzeugt das richtige Ergebnis (im Wesentlichen das Ergebnis einer Zusammenführung), während Ihre Methode die Änderungen im aktuellen Zweig wegwerfen und alle Änderungen vom gemeinsamen Vorgänger bis zu stuff - nicht nur die, die in dieser einen Übertragung enthalten sind.

2 Stimmen

@Tobias Kienzler: Ich bin davon ausgegangen, dass sich Ihr Ausgangspunkt hinreichend von der Muttergesellschaft von stuff dass das Ergebnis der Rosinenpickerei dazu führen würde A y B mit einem anderen Inhalt als dem, den sie in der Übertragung haben stuff . Aber wenn es nur das Gleiche wäre, haben Sie recht - Sie könnten einfach tun, was Sie sagen.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X