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.

48voto

cminatti Punkte 4526

Cherry Pick bedeutet, Änderungen aus einem bestimmten "Commit" auszuwählen. Die einfachste Lösung, um alle Änderungen bestimmter Dateien auszuwählen, ist die Verwendung von

 git checkout source_branch <paths>...

Ein Beispiel:

$ git branch
* master
  twitter_integration
$ git checkout twitter_integration app/models/avatar.rb db/migrate/20090223104419_create_avatars.rb test/unit/models/avatar_test.rb test/functional/models/avatar_test.rb
$ git status
# On branch master
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#   new file:   app/models/avatar.rb
#   new file:   db/migrate/20090223104419_create_avatars.rb
#   new file:   test/functional/models/avatar_test.rb
#   new file:   test/unit/models/avatar_test.rb
#
$ git commit -m "'Merge' avatar code from 'twitter_integration' branch"
[master]: created 4d3e37b: "'Merge' avatar code from 'twitter_integration' branch"
4 files changed, 72 insertions(+), 0 deletions(-)
create mode 100644 app/models/avatar.rb
create mode 100644 db/migrate/20090223104419_create_avatars.rb
create mode 100644 test/functional/models/avatar_test.rb
create mode 100644 test/unit/models/avatar_test.rb

Quellen und vollständige Erklärung http://jasonrudolph.com/blog/2009/02/25/git-tip-how-to-merge-specific-files-from-another-branch/

UPDATE:

Mit dieser Methode wird Git die Datei nicht MERGE, sondern überschreibt lediglich alle anderen Änderungen im Zielzweig. Sie müssen die Änderungen manuell zusammenführen:

$ git diff HEAD filename

8 Stimmen

Das dachte ich auch Dies schlägt jedoch fehl, wenn sich die Dateien am beide Zweige, da er die Änderungen des aktuellen Zweigs verwirft

0 Stimmen

Sie haben Recht, es muss klargestellt werden, dass Git auf diese Weise nicht MERGE, sondern nur override macht. Sie können dann "git diff HEAD filename" ausführen, um zu sehen, was sich geändert hat, und die Zusammenführung manuell vornehmen.

0 Stimmen

Das hat bei mir gut funktioniert. Ein Kollege hatte einen Kommentar zu einem Pull Request abgegeben, dass einige Änderungen in einen separaten Request aufgeteilt werden sollten, um die Probleme klar zu trennen. Ihre Methode hat in diesem Fall gut funktioniert.

33voto

kubanczyk Punkte 4395

Der Vollständigkeit halber möchte ich sagen, dass es für mich am besten funktioniert:

git show YOURHASH --no-color -- file1.txt file2.txt dir3 dir4 | git apply -3 --index -

Es tut genau das, was OP will. Sie löst Konflikte bei Bedarf, ähnlich wie die merge tut es. Es tut add aber nicht commit Ihre neuen Änderungen, siehe mit status .

6 Stimmen

Das ist wunderschön.

0 Stimmen

Danke! Können Sie erwähnen, was die 3 ist für ( ... git apply -3 --index ... )?

4 Stimmen

-3 bedeutet, dass ein "3-way merge fallback" verwendet werden soll. Das bedeutet in der Praxis, dass Git bekannte Konfliktmarkierungen einfügen oder eine bereits vorgenommene Änderung umgehen kann. Der Standard git apply ist für meinen Geschmack zu streng, es weigert sich, bei der geringsten Abweichung den gesamten Patch anzuwenden.

22voto

eliastg Punkte 329

Manchmal könnte es einfacher sein, die Zur Kasse um bestimmte Dateien aus einer Übertragung zu holen. Meiner Meinung nach gibt es Ihnen mehr Kontrolle, und es ist nicht notwendig, zu überprüfen und unstaging nach einem Cherrypick.

Ich würde es folgendermaßen machen:

git checkout <branch|hash> -- path/to/file1 path/to/filen

Dann unstage die notwendigen Änderungen, um den Code anzupassen und testen Sie es, bevor Sie Commit tun. Wenn alles wie erwartet funktioniert, dann festschreiben.

0 Stimmen

Identisch mit mehreren vorhandenen Antworten.

18voto

funroll Punkte 33821

Ich würde einfach alles herauspicken und dann das tun:

git reset --soft HEAD^

Dann würde ich die Änderungen, die ich nicht möchte, rückgängig machen und eine neue Übertragung vornehmen.

1 Stimmen

Dies ist nicht effizient, wenn die Rosinenpickerei zu vielen Konflikten mit Dateien führen würde, die Sie nicht benötigen.

12voto

Indomitable Punkte 748

Utilice git merge --squash branch_name werden alle Änderungen aus dem anderen Zweig übernommen und ein Commit für Sie vorbereitet. Entfernen Sie nun alle nicht benötigten Änderungen und lassen Sie die gewünschte Änderung stehen. Und git wird nicht wissen, dass es eine Zusammenführung gab.

0 Stimmen

Danke, ich wusste nichts von dieser Zusammenführungsoption. Es ist eine brauchbare Alternative, wenn man den größten Teil eines ganzen Zweiges herauspicken möchte (aber im Gegensatz zu Cherry-Pick funktioniert es nicht, wenn es keinen gemeinsamen Vorfahren gibt)

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