Starten Sie ein einzelnes Git-Commit neu

116

Gibt es eine Möglichkeit, ein einzelnes Commit von einem Zweig auf einen anderen Zweig umzustellen?

Ich habe diese Zweigstruktur:

-- -- -- -- -- (Master)
            \
              -- -- -- -- -- XX (Feature-branch)

Alles, was ich tun möchte, ist, das letzte Commit von Feature-branchauf Master neu zu setzen und Feature-branchein Commit zurückzusetzen.

-- -- -- -- -- XX (Master)
            \
              -- -- -- -- -- (Feature-branch)

Wie mache ich das?

Kevin Meyer
quelle
3
Wenn Sie eine beliebige Anzahl von Commits neu festlegen können, warum fragen Sie dann nach einer Neueinstellung eines einzelnen Commits? Wenn ich in SO Fragen stellen könnte, würde ich fragen, was der Unterschied zwischen Rebasing (ein einziges Commit) und Cherry-Picking ist.
Val
9
Weil ich nicht wusste, dass es Kirschernte gibt, und ich mache "Faff about on branch", "Get request for fix on different branch", "fix it", "Commit to false branch", "D'OH!" genug, dass es nützlich war, die Frage zu stellen.
Kevin Meyer

Antworten:

117

Sie können XX auswählen, um zu meistern.

git checkout master
git cherry-pick <commit ID of XX>

Und entfernen Sie das letzte Commit mit git reset aus dem Feature-Zweig.

git checkout Feature-branch
git reset --hard HEAD^
tewe
quelle
61
Wie kann eine Frage, die speziell "Git Rebase ..." genannt wird, die akzeptierte Antwort haben, als einen Kirschpickel zu enthalten, der ein völlig anderes Konzept darstellt und manchmal per se als unrein angesehen wird?
Bondax
1
Ich bin mir nicht sicher, ob dies relevant ist, aber das Commit, das ich neu erstellen wollte, hatte einige Dateien, die verschoben wurden, und cherry-pickließ sie so erscheinen, als ob sie vom alten Speicherort gelöscht und am neuen Speicherort erstellt wurden. Ich nehme an, Rebase hätte sich darum gekümmert, aber jetzt habe ich mich stromaufwärts geschoben, damit ich das nicht testen kann. Seien Sie auf jeden Fall vorsichtig, wenn Sie eine ähnliche Situation haben.
Waldyrious
Hinweis: Um Änderungen Feature-branchan der Herkunft vorzunehmen , müssen Sie dies tun, git push -f origin Feature-branchda Ihre Änderung Feature-branchjetzt als 1 Commit hinter dem angesehen wird origin/Feature-branch.
Jojo
1
Was ist der praktische Unterschied zwischen dieser Lösung und der von CharlesB ?
Lii
96
git rebase --onto master branch~1 branch 

Darin heißt es: "Den Bereich der Festschreibungen zwischen dem letzten Zweig und dem Zweig (dh dem XX-Festschreiben) an der Spitze des Hauptzweigs neu festlegen."

Nach diesem Vorgang wird der branchTipp beim Festschreiben verschoben XX, sodass Sie ihn mit zurücksetzen möchten

git checkout branch
git reset --hard branch@{1}^

Darin heißt es: "Setzen Sie die Verzweigungsspitze vor ihrem vorherigen Status auf das Commit zurück."

Ein Kirschpickel ist also eine einfachere Lösung ...

CharlesB
quelle
5
Dies scheint für mich nicht zu funktionieren, ich verliere die Commits vor XX und der Zweig wird neu aufgebaut, um mit einem einzigen Commit zu meistern, aber ich habe ihn noch nie verwendet, --ontosodass ich möglicherweise etwas falsch mache. Übrigens sagte der OP Rebase, aber es scheint, als wolle er einen Kirschpickel machen.
Tewe
1
Mein Fehler, Rebase verschiebt tatsächlich den Zweig auf Master, es muss zurückgesetzt werden
CharlesB
1
Was ist der praktische Unterschied zwischen dieser Lösung und der von Tewe ?
Lii
1
@Lii das einzige was ich sehen kann ist, dass es 3 Schritte anstelle von 4 verwendet
CharlesB
50

Das ist eigentlich ganz einfach. Die Lösung besteht darin, eine interaktive Rebase durchzuführen und alle Commits zu "löschen", die Sie nicht in die Rebase aufnehmen möchten.

git rebase -i <target_branch>Wo target_branchist der Zweig, auf den Sie zurückgreifen möchten?

Anschließend bearbeiten Sie die geöffnete Datei und pickdie gewünschten Commits und drop(oder dkurz) alle Commits, die Sie nicht mitbringen möchten.

hrdwdmrbl
quelle
6
IMO eine viel bessere Lösung, und es geht tatsächlich um die Frage.
GabrielOshiro
1

@ Charles Antwort ist korrekt. Wie auch immer, ich habe dies so oft verwendet, vor allem, um bestimmte Konfigurationen in einem Projekt neu zu starten

  * a8f9182 (HEAD -> Produktion) Produktionskonfiguration
  | * daa18b7 (Vor-) Vorproduktionskonfiguration
  | /  
  | * d365f5f (lokale) lokale Konfiguration
  | /  
  * 27d2835 (dev) erstaunliche neue Funktion, die die Welt retten wird
* | 56d2467 (Master) langweiliger Stand der Technik für das Projekt
| /

dass ich einen neuen Befehl dafür erstelle:

$ cat ~ / bin / git-rebaseshot 
COMMIT = $ 1
DEST = $ {2: -HEAD}
git rebase $ {COMMIT} ^ $ {COMMIT} --onto $ DEST

Normalerweise möchten Sie Zweigstellennamen für diesen Befehl automatisch vervollständigen. Fügen Sie ihn hinzu, indem Sie diese Funktion beziehen (Hinzufügen zu .bashrc oder .profile):

_git_rebaseshot () 
{ 
    __gitcomp_nl "$ (__ git_refs)"
}}

git autocomplete sucht danach

Sie können diesen Befehl folgendermaßen verwenden:

# rebase config on prepro on actual HEAD
$ git rebaseshot prepro 
# rebase config on local onto dev
$ git rebaseshot local dev
# rebase production config on master
$ git rebaseshot pro master

Wenn Sie Features richtig unterteilen, sind die Möglichkeiten endlos.

* a8f9182 (HEAD -> postgres) BBDD-Konfiguration
* a8f9182 (lokale) lokale Konfiguration
* a8f9182 (Debug) Konfiguration auf Protokollebene
* a8f9182 (dev) neue Funktion
|

Ich denke, das ist es, was Quilt- Leute gerne machen.

Dieser Befehl funktioniert trotzdem mit allen von Ihnen angegebenen sha / ref:

$ git rebaseshot <Feature branch> master
$ git rebaseshot <commit of XX> master
Albfan
quelle
//, Können Sie einen Link zu einem Projekt erstellen, in dem wir dies in Aktion sehen können?
Nathan Basanese
Filialen, die für einen Rebaseshot verfügbar sind, werden naturgemäß nicht außerhalb des lokalen Repos gebunden. Erstellen Sie einfach mehrere Zweige über dem Master (Protokollebene, Datenbankverbindung, Konfiguration) und verwenden Sie den Befehl zwischen ihnen. Ist deutlich zu sehen, wie sich das auswirkt.
Albfan
// Ich bin auf einige Probleme gestoßen. Ich werde es noch einmal versuchen.
Nathan Basanese
0

Hier ist eine weitere Option:

  1. Stellen Sie sicher, dass Sie eine Fernbedienung mit einer Kopie des Funktionszweigs haben
  2. Löschen Sie den lokalen Feature-Zweig
  3. Erstellen und Auschecken eines neuen Zweigs mit demselben Namen wie der alte Feature-Zweig, den Sie gerade aus dem Master gelöscht haben
  4. Wählen Sie das Commit aus der Remote-Kopie des gewünschten Feature-Zweigs aus.

Befehle sehen aus wie:

git checkout Feature-branch
git push -u origin HEAD
git checkout master
git branch -D Feature-branch
git checkout -b Feature-branch
git cherry-pick HASH-OF-XX

Es ist kein Rebase-Befehl, nein, aber es ist eine Rebase im Geiste.

cdmo
quelle