it-swarm.com.de

Wie git-cherry-pick nur Änderungen an bestimmten Dateien?

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

Angenommen, das Git-Commit mit dem Namen stuff enthält Änderungen an Dateien A, B, C und D, aber ich möchte nur die Änderungen von stuff zusammenführen zu Dateien A und B. Es klingt wie ein Job für git cherry-pick, aber cherry-pick kann nur ganze Commits zusammenführen, keine Teilmenge der Dateien.

497
Tobias Kienzler

Ich würde es mit cherry-pick -n (--no-commit) machen, mit dem Sie das Ergebnis überprüfen (und ändern) können, bevor Sie Folgendes festlegen:

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 die meisten Änderungen nicht gewünscht sind, anstatt einzelne Pfade zu überprüfen (der mittlere Schritt), können Sie alles zurücksetzen und dann hinzufügen, was Sie möchten:

# 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 .
598
Cascabel

Die anderen Methoden haben bei mir nicht funktioniert, da beim Festschreiben viele Änderungen und Konflikte an vielen anderen Dateien aufgetreten sind. Was ich mir ausgedacht habe, war einfach

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

Tatsächlich werden die Dateien nicht add oder es wird kein Commit für Sie durchgeführt, sodass Sie möglicherweise nachverfolgen müssen

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

Oder wenn Sie das Hinzufügen überspringen möchten, können Sie das Argument --cached für git apply verwenden.

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

Normalerweise benutze ich das -p -Flag mit einer Git-Prüfung aus dem anderen Zweig, die ich einfacher und granularer finde als die meisten anderen Methoden, auf die ich gestoßen bin.

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 einen Dialog, in dem Sie gefragt werden, welche Änderungen Sie in "Blobs" vornehmen möchten. Dies funktioniert so ziemlich für jeden Teil der fortlaufenden Codeänderung, für den Sie dann y (Yes) n (No) etc signalisieren können jedes Stück Code.

Die Option -p oder patch funktioniert für eine Vielzahl von Befehlen in git, einschließlich git stash save -p, mit denen Sie auswählen können, was Sie aus Ihrer aktuellen Arbeit verstecken möchten

Ich verwende diese Technik manchmal, wenn ich viel Arbeit geleistet habe und es herauslösen und in mehr themenbasierten Commits festlegen möchte, indem ich git add -p verwende und wähle, was ich für jedes Commit möchte :)

67
Tyrone Wilson

Vielleicht ist der Vorteil dieser Methode gegenüber Jefromis Antwort , dass Sie sich nicht merken müssen, welches Verhalten von git reset das richtige ist :)

 # 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
41
Mark Longair

Cherry Pick ist die Auswahl von Änderungen aus einem bestimmten "Commit". Die einfachste Lösung ist, alle Änderungen an bestimmten Dateien auszuwählen, die verwendet werden sollen

 git checkout source_branch <paths>...

Zum 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/

AKTUALISIEREN:

Bei dieser Methode wird die Datei von git nicht zusammengeführt, sondern nur alle anderen Änderungen überschrieben, die im Zielzweig vorgenommen wurden. Sie müssen die Änderungen manuell zusammenführen:

$ git diff HEAD Dateiname

25
cminatti

Mit 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 belassen Sie die gewünschte. Und git wird nicht wissen, dass es eine Verschmelzung gab.

11
Indomitable

Ich würde einfach alles auswählen und dann Folgendes tun:

git reset --soft HEAD^

Dann würde ich die Änderungen, die ich nicht möchte, rückgängig machen und dann ein neues Commit durchführen.

10
funroll

Die Situation:

Sie befinden sich in Ihrem Zweig, sagen wir master, und Sie haben Ihr Commit für jeden anderen Zweig. Sie müssen nur eine Datei aus diesem bestimmten Commit auswählen.

Der Ansatz:

Schritt 1: Kasse auf 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 hinzufügen und festschreiben.

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

Ich habe einen anderen Weg gefunden, der jede widersprüchliche Verschmelzung bei der Kirschernte verhindert, die meiner Meinung nach leicht zu merken und zu verstehen ist. Da Sie tatsächlich kein Commit auswählen, sondern einen Teil davon, müssen Sie es zuerst aufteilen und dann ein Commit erstellen, das Ihren Anforderungen entspricht, und es auswählen.

Erstellen Sie zunächst einen Zweig aus dem Commit, den Sie aufteilen möchten, und checken Sie ihn aus:

$ git checkout COMMIT-TO-SPLIT-SHA -b temp

Setzen Sie dann das vorherige Commit zurück:

$ git reset HEAD~1

Fügen Sie dann die Dateien/Änderungen hinzu, die Sie auswählen möchten:

$ git add FILE

und begebe es:

$ git commit -m "pick me"

notieren Sie sich den Commit-Hash, nennen wir ihn PICK-SHA und kehren Sie zu Ihrem Hauptzweig zurück, indem Sie beispielsweise den Checkout erzwingen:

$ git checkout -f master

und wählen Sie das Commit aus:

$ git cherry-pick PICK-SHA

jetzt können Sie den temporären Zweig löschen:

$ git branch -d temp -f
4
Alexey

Füge einen Zweig in einen neuen zusammen (Squash) und entferne die nicht benötigten Dateien:

git checkout master
git checkout -b <branch>
git merge --squash <source-branch-with-many-commits>
git reset HEAD <not-needed-file-1>
git checkout -- <not-needed-file-1>
git reset HEAD <not-needed-file-2>
git checkout -- <not-needed-file-2>
git commit
2
nvd