Pomaknite zadnju urezivanje u novu granu pomoću Git-a

Htio bih premjestiti posljednjih nekoliko obveza koje sam napravio da se dočepam nove grane i dovedem gospodara natrag prije nego što su počinili. Nažalost, moj git -fu još nije dovoljno jak, pomoć?

odnosno Kako mogu ići iz ovoga

 master A - B - C - D - E 

na ovo?

 newbranch C - D - E / master A - B 
3467
27 окт. Postavio Mark A. Nicolosi 27. listopada 2009-10-27 06:07 '09 u 6:07 am 2009-10-27 06:07
@ 8 odgovora

Idite u novu granu

Ako ne postoje druge okolnosti, to se može lako učiniti razgranatim i povratnim.

* 1 će samo "izgubiti" urezivanje od glavne grane, ali ne brinite, imat ćete ove naredbe u novoj podjeli!

UPOZORENJE: Kada koristite Git verzije 2.0 i kasnije, ako je kasnije git rebase nova grana u izvornoj grani ( master ), možda ćete trebati eksplicitnu opciju --no-fork-point tijekom rebase kako biste izbjegli gubitak prijenosnih prijenosa. Prisutnost branch.autosetuprebase always postavljena čini je vjerojatnijom. Za detalje, pogledajte John Mellora .

Idite na postojeću granu

UPOZORENJE: Gore navedena metoda radi jer stvarate novu granu s prvom naredbom: git branch newbranch . Ako želite koristiti postojeću granu , prije izvođenja git reset --hard HEAD~3 morate spojiti svoje promjene u postojeću granu . Ako ne spojite svoje promjene, one će biti izgubljene. Dakle, ako radite s postojećom granom, izgledat će ovako:

4382
27 окт. odgovor dao sykora 27 list . 2009-10-27 06:15 '09 u 6:15 am 2009-10-27 06:15

Za one koji se pitaju zašto radi (kao što sam bio na početku):

Želite se vratiti na C i pomaknuti D i E u novu granu. Prvo ovako izgleda:

 ABCDE (HEAD) ↑ master 

Nakon git branch newBranch :

border=0
  newBranch ↓ ABCDE (HEAD) ↑ master 

Nakon git reset --hard HEAD~2 :

  newBranch ↓ ABCDE (HEAD) ↑ master 

Budući da je grana samo pokazivač, majstor je pokazao na posljednju naredbu. Kada ste kreirali newBranch, jednostavno ste napravili novi pokazivač na posljednje urezivanje. Zatim, pomoću git reset , premjestili ste glavni pokazivač natrag na dva urezivanja. Ali budući da niste premjestili novu granu, ona još uvijek ukazuje na počinjenje koje je izvorno napravio.

801
23 июля '11 в 1:37 2011-07-23 01:37 odgovor je dao Ryan Lundy 23. srpnja '11 u 1:37 2011-07-23 01:37

Općenito ...

U ovom slučaju, najbolja opcija je metoda otvorenog sykora. Ali ponekad to nije najlakša i najopćenitija metoda. Za opću metodu koristite git cherry-pick:

Za postizanje željenog OP-a to je proces u dva koraka:

Korak 1 - napomena koja popravlja traženi master na newbranch

trčanje

 git checkout master git log 

Imajte na umu da vam newbranch (recimo, 3) obvezuju na newbranch . Ovdje ću koristiti:
C obvezu: 9aa1233
D 453ac3d : 453ac3d
E 612ecb3 : 612ecb3

Napomena. , Možete koristiti prvih sedam znakova ili cijeli hash urezivanja.

Korak 2 - Stavite ih na newbranch

 git checkout newbranch git cherry-pick 612ecb3 git cherry-pick 453ac3d git cherry-pick 9aa1233 

ILI (u git 1.7.2+ koristite raspone)

 git checkout newbranch git cherry-pick 612ecb3~1..9aa1233 

git cherry-pick primjenjuje ove tri obveze prema novoj grani.

315
07 февр. Odgovor Ivan 07. veljače. 2012-02-07 19:58 '12 u 19:58 2012-02-07 19:58

Drugi način za to je korištenje samo 2 naredbe. Također čuva vašu trenutnu radnu cjelinu.

 git checkout -b newbranch # switch to a new branch git push . +HEAD~3:master # make master point to some older commit 

Sposobnost push . - Ovo je dobar trik.

Kasnije uređivanje: sada kada znam za git branch -f , to je ispravan način:

 git checkout -b newbranch # switch to a new branch git branch -f master HEAD~3 # make master point to some older commit 

Isto, ali manje "magično"

235
26 марта '14 в 11:13 2014-03-26 11:13 odgovor je dat aragaer 26. ožujka '14 u 11:13 2014-03-26 11:13

Većina prethodnih odgovora je opasno pogrešna!

NE učinite to:

 git reset --keep HEAD~3 git checkout -t -b newbranch git cherry-pick ..HEAD@{2} 
  • Prvo, on odbacuje posljednja 3 --hard ( --keep je sličan - --hard , ali je sigurniji, budući da ne uspijeva, umjesto da baca neobavezane promjene).
  • Zatim onesposobljava newbranch .
  • Onda je on trešnja pijucima da ove 3 vraća natrag u newbranch . Budući da se više ne odnose na granu, ona to radi s git reflog : HEAD@{2} je popravak koji HEAD koristi za referenciranje do 2 operacije natrag, tj. prije nego što smo 1. provjeravali newbranch i 2. koristili git reset za odbacivanje 3 newbranch .

Upozorenje: reflog je prema zadanim postavkama omogućen, ali ako ste ga ručno onemogućili (na primjer, koristeći spremište golih gitova), nećete moći dobiti 3 git reset --keep HEAD~3 nakon pokretanja git reset --keep HEAD~3 .

Alternativa koja se ne oslanja na reflog je:

 git branch -t newbranch git reset --hard HEAD~3 git checkout newbranch 

je da ostavljaju reflog u pogrešnom stanju. git vidi newbranch kao razgranatu granu do revizije, koja uključuje 3 reset --hard , a zatim reset --hard prepisuje povijest reset --hard za uklanjanje, pa ih sljedeći put kada pokrenete git rebase ispusti ih kao i svaki drugi uklonjen iz uzvodnog toka.

Ali u ovom konkretnom slučaju, želimo da se te 3 fiksacije smatraju dijelom teme. Da bismo to postigli, moramo ga odbaciti uzvodno u ranijoj reviziji koja ne uključuje 3 obveze. To je ono što moja predložena rješenja čine, pa oboje ostavljaju reflog u ispravnom stanju.

Pojedinosti potražite u definiciji --fork-point u git rebase i git stapanju baze .

179
07 апр. Odgovor dao John Mellor 7. travnja 2016-04-07 01:38 '16 u 13:38 2016-04-07 01:38

To ih ne "pomiče" u tehničkom smislu, ali ima isti učinak:

 A--B--C (branch-foo) \ ^-- I wanted them here! \ D--E--F--G (branch-bar) ^--^--^-- Opps wrong branch! While on branch-bar: $ git reset --hard D # remember the SHAs for E, F, G (or E and G for a range) A--B--C (branch-foo) \ \ D-(E--F--G) detached ^-- (branch-bar) Switch to branch-foo $ git cherry-pick E..G A--B--C--E'--F'--G' (branch-foo) \ E--F--G detached (This can be ignored) \ / D--H--I (branch-bar) Now you won't need to worry about the detached branch because it is basically like they are in the trash can waiting for the day it gets garbage collected. Eventually some time in the far future it will look like: A--B--C--E'--F'--G'--L--M--N--... (branch-foo) \ \ D--H--I--J--K--.... (branch-bar) 
26
19 окт. Odgovor daje Sukima 19. listopada. 2013-10-19 17:12 '13 u 17:12 2013-10-19 17:12

Da biste to učinili bez ponovnog pisanja povijesti (npr., Ako ste već kliknuli na urezivanje):

 git checkout master git revert <commitID(s)> git checkout -b new-branch git cherry-pick <commitID(s)> 

Obje grane se mogu pritisnuti bez napora!

17
21 янв. odgovor dati teh_senaus 21. siječnja 2016-01-21 19:10 '16 u 19:10 2016-01-21 19:10

Ako takva situacija:

 Branch one: ABCDEFJLM \ (Merge) Branch two: GIKN 

Završio sam:

 git branch newbranch git reset --hard HEAD~8 git checkout newbranch 

Očekivao sam da će popravak biti GLAVA, ali počiniti L je sada ...

Sletjeti na pravo mjesto u povijesti, lakše je raditi s hašemom.

 git branch newbranch git reset --hard ######### git checkout newbranch 
11
20 сент. Odgovor daje Darkglow 20. rujna. 2013-09-20 13:17 '13 u 13:17 2013-09-20 13:17