Ponovi višestruko git urezivanje

Imam git repozitorij koji izgleda ovako:

 A -> B -> C -> D -> HEAD 

Želim da glava grane pokazuje na A, to jest, želim da B, C, D i HEAD nestanu, i želim da glava bude sinonim za A.

Izgleda da mogu ili pokušati ponovno instalirati (ne primjenjuje se, jer sam kliknuo promjene između njih) ili se vratio. Ali kako da vratim višestruke objave? Vraćam li se jedan po jedan? Je li poredak važan?

499
23 сент. postavila Bill 23. rujna 2009-09-23 03:27 '09 u 3:27 am 2009-09-23 03:27
@ 11 odgovora

Proširenje onoga što sam napisao u komentarima

Opće pravilo je da ne smijete prepravljati (mijenjati) priču koju ste objavili, jer bi netko mogao temeljiti svoj rad na njoj. Ako ponovno napišete (promijenite) priču, imat ćete problema s spajanjem njihovih promjena i ažuriranjem.

Dakle, rješenje je stvoriti novu naredbu koja vraća promjene koje se želite riješiti. To možete učiniti pomoću git revert .

Imate sljedeću situaciju:

 A <- B <- C <- D <- master <- HEAD

(strelice se ovdje odnose na smjer pokazivača: "roditeljska" veza u slučaju urezivanja, gornja fiksacija u slučaju grane grane (odgovor grane) i naziv grane u slučaju HEAD veze).

Ono što trebate stvoriti je sljedeće:

 A <- B <- C <- D <- [(BCD) ^ - 1] <- master <- HEAD

gdje "[(BCD) ^ - 1]" znači urezivanje, koje vraća promjene u urezivanja od B, C, D. Matematika nam govori da je (BCD) ^ - 1 = D ^ -1 C ^ -1 B ^ - 1, stoga, potrebnu situaciju možete dobiti pomoću sljedećih naredbi:

 $ git revert --no-commit D $ git revert --no-commit C $ git revert --no-commit B $ git commit -m "the commit message" 

Alternativno rješenje bilo bi provjeravanje sadržaja urezivanja A i unošenje tog stanja:

 $ git checkout -f A -- . $ git commit -a 

Tada ćete imati sljedeću situaciju:

 <- B <- C <- D <- A '<- master <- HEAD

Kraj A 'ima isti sadržaj kao i urezivanje A, ali je različita predaja (poruka urezivanja, roditelji, datum izvršenja).

Jeff Ferlandovo rješenje , modificirano od Charlesa Baileyja , temelji se na istoj ideji, ali koristi git reset :

 $ git reset --hard A $ git reset --soft @{1} # (or ORIG_HEAD), which is D $ git commit 
778
24 сент. Odgovor dao Jakub Narębski 24. rujna. 2009-09-24 11:44 '09 u 11:44 2009-09-24 11:44

Da biste to učinili, samo trebate koristiti naredbu vraćanja, navodeći raspon urezivanja koje želite vratiti.

Uzimajući u obzir vaš primjer, morat ćete to učiniti (ako ste na "glavnoj" grani):

 git revert master~3..master 
border=0

To će stvoriti novu predaju u vašoj lokalnoj mreži s obrnutim B, C i D obvezama (što znači da poništava promjene koje su izvršene tim obvezama):

 A <- B <- C <- D <- BCD' <- HEAD 
126
31 июля '12 в 18:00 2012-07-31 18:00 Odgovor daje Victor 31. srpnja 2012. u 18 sati. 2012-07-31 18:00
 git reset --hard a git reset --mixed d git commit 

Ovo će djelovati kao povrat za sve odjednom. Dajte dobru poruku o fiksaciji.

36
23 сент. Odgovor dao Jeff Ferland 23. rujna 2009-09-23 03:45 '09 u 3:45 2009-09-23 03:45

Poput Jakubovog odgovora, omogućuje vam jednostavno odabir uzastopnih obveza za povratak.

 # revert all commits from B to HEAD, inclusively $ git revert --no-commit B..HEAD $ git commit -m 'message' 
34
31 июля '14 в 21:49 2014-07-31 21:49 odgovor je dao konyak 31. srpnja '14. u 21:49 2014-07-31 21:49

Prvo provjerite je li vaša radna kopija nepromijenjena. zatim:

 git diff HEAD commit_sha_you_want_to_revert_to | git apply 

i onda samo popravi. Ne zaboravite dokumentirati razlog vraćanja.

19
09 сент. odgovor je dan mateusz.fiolka 09 sep . 2014-09-09 16:13 '14 u 16:13 2014-09-09 16:13

Čist način sam našao korisnim

 git revert --no-commit HEAD~3.. 

Ova naredba vraća posljednja 3 urezivanja s jednom predajom.

Također ne prepisuje povijest.

12
29 марта '17 в 3:00 2017-03-29 03:00 odgovor je dan duboko 29. ožujka 2006. u 3:00 2017-03-29 03:00

Toliko sam uzrujana da se na ovo pitanje ne može jednostavno odgovoriti. Svako drugo pitanje odnosi se na to kako se ispravno vratiti i spasiti povijest. Ovo pitanje kaže: "Želim da glava grane pokaže na A, to jest, želim da B, C, D i GLAVA nestanu , i želim da glava bude sinonim za A."

 git checkout <branch_name> git reset --hard <commit Hash for A> git push -f 

Mnogo sam naučio čitanjem Yakubovog posta, ali neki tip u tvrtki (s pristupom na našu testnu granu bez Pull-Request) kliknuo je kao 5 loših obveza pokušavajući ispraviti i ispraviti pogrešku i ispraviti pogrešku koju je napravio , Ne samo to, već jedan ili dva povlačeći zahtjeve koji su sada bili loši. Zato zaboravite na to, pronašao sam zadnji dobar popravak (abc1234) i pokrenuo sam osnovnu skriptu:

 git checkout testing git reset --hard abc1234 git push -f 

Rekao sam ostalim petorici koji rade u ovom repo-u da će u posljednjih nekoliko sati najbolje primijetiti njihove promjene i da će iz posljednjeg testa izbrisati / re-Branch. Kraj priče.

11
12 июля '16 в 2:29 2016-07-12 02:29 odgovor je dat Suamereu 12. srpnja '16. u 2:29 sati 2016-07-12 02:29

Najjednostavniji način da vratite grupu urezivanja u zajedničko spremište (koje ljudi koriste, a želite zadržati povijest) jest da koristite git revert zajedno s git rev-list . Potonji će vam dati popis obveza, prvi će se vratiti.

Postoje dva načina za to. Ako želite ponovljeno višestruko urezivanje u jednom urezivanju koristiti:

 for i in `git rev-list <first-commit-sha>^..<last-commit-sha>`; do git revert -n $i; done 

To će dovesti do vraćanja skupine potrebnih obveza, ali ostavite sve promjene na radnom stablu, trebate ih popraviti kao i obično.

Druga je mogućnost imati jednu obvezu za svaku poništenu promjenu:

 for i in `git rev-list <first-commit-sha>^..<last-commit-sha>`; do git revert --no-edit -s $i; done 

Na primjer, ako imate stablo fiksacije tipa

  o---o---o---o---o---o---> fff eee ddd ccc bbb aaa 

za povratak promjena s eee na bbb, trčanje

 for i in `git rev-list eee^..bbb`; do git revert --no-edit -s $i; done 
4
04 авг. odgovor je dat Ruslan Kabalin 04 aug. 2011-08-04 14:29 '11 u 14:29 sati 2011-08-04 14:29

Ovo je proširenje jednog od rješenja pruženih kao odgovor na Yakub.

Suočio sam se sa situacijom u kojoj su obveze koje su mi trebale biti odbačene bile pomalo komplicirane, a neke od obveza bile su spajanje, a ja nisam trebala prepisivati ​​povijest. Nisam mogao koristiti niz naredbi za git revert jer sam na kraju naišao na sukobe između dodanih promjena vraćanja. Završio sam sljedeće korake.

Prvo provjerite sadržaj ciljnog urezivanja, ostavljajući HEAD na vrhu ogranka:

 $ git checkout -f <target-commit> -- . 

(Povjerenje se tumači kao urezivanje, ne kao datoteka, već se odnosi na trenutni direktorij.)

Zatim odredite koje su datoteke dodane dovršenim obvezama i stoga ih je potrebno izbrisati:

 $ git diff --name-status --cached <target-commit> 

Dodane datoteke trebale bi se pojaviti s "A" na početku retka, i ne bi trebalo biti drugih razlika. Sada, ako je potrebno izbrisati neke datoteke, izvršite ih da biste izbrisali:

 $ git rm <filespec>[ <filespec> ...] 

Konačno, dovršite vraćanje:

 $ git commit -m 'revert to <target-commit>' 

Ako želite, pobrinite se da se vratimo u željeno stanje:

 $git diff <target-commit> <current-commit> 

Ne bi trebalo biti nikakvih razlika.

3
08 нояб. Odgovor daje Warren Dew 08 Nov. 2016-11-08 09:39 '16 u 9:39 2016-11-08 09:39

Nitko od njih nije radio za mene, tako da sam imao tri obveze za povratak (posljednje tri obveze), pa sam učinio:

 git revert HEAD git revert HEAD~2 git revert HEAD~4 git rebase -i HEAD~3 # pick, squash, squash 

Radila kao šarm :)

0
24 янв. Odgovor je dat Dorian 24 Jan. 2017-01-24 03:28 '17 u 3:28 2017-01-24 03:28

Ako želite privremeno raspakirati funkciju, možete koristiti nekoliko sljedećih naredbi.

Ovako to funkcionira.

git log - prilično = oneline | grep 'feature_name' | cut-d '-f1 | xargs -n1 git se vraća - ne-uređivanje

-1
11 февр. Odgovor daje Ajit Singh 11. veljače. 2016-02-11 21:47 '16 u 21:47 2016-02-11 21:47

Ostala pitanja o oznakama ili postavi pitanje