Domanda

Ho apportato una modifica a una sceneggiatura e l'ho impegnata. Quindi ho apportato alcune altre modifiche e le ho trasferite in un repository remoto e simili.

Poi mi sono reso conto che il primo cambiamento che ho menzionato era stupido e voglio annullarlo. Posso " non applicare " che commette, senza copiare / incollare manualmente il diff?

Ad esempio: ho due file, a.py e b.py:

Commit 1:
I delete a function in a.py

Commit 2:
I change a few lines in b.py

Commit 3:
I change the docstring in a.py

Posso annullare la cancellazione di quella funzione e farla apparire come " commit 4 " (anziché eliminare il commit 1)

È stato utile?

Soluzione

Sì, puoi usare git revert per questo. Consulta la sezione del manuale di git su questo per maggiori informazioni.

L'essenza è che puoi dire:

git revert 4f4k2a

Dove 4f4k2a è l'id del commit che desideri annullare e proverà a annullarlo.

Altri suggerimenti

Solo un commento:

git revert aCommit

ripristina il tutto commit (come in " tutti i file parte del commit "):
calcola una patch inversa, la applica su HEAD e commette.

Quindi due problemi qui (il primo è facilmente risolvibile):

  • commette sempre, quindi potresti voler aggiungere l'opzione -no-commit : " git revert --no-commit aCommit " ;: questo è utile quando ripristini più di un commit " effetto al tuo indice di fila.
  • non si applica per un file specifico (cosa succede se a.py faceva parte di un commit con altre 1000 modifiche che potresti non voler ripristinare)?
    Per questo, se desideri estrarre file specifici come in un altro commit, dovresti vedere git-checkout , in particolare la sintassi git checkout <commit> <filename> (che non è esattamente ciò di cui hai bisogno in questo caso)

Easy Git (Elijah Newren) ha provato a portare un altro " completa ripristina " alla Git Mailing list ; ma senza molto successo:

  

Le persone occasionalmente vogliono " ripristinare le modifiche " ;.

     

Ora, questo potrebbe essere:

     
      
  • le modifiche tra 32 e 29 revisioni fa,
  •   
  • potrebbero essere tutte le modifiche dall'ultimo commit,
  •   
  • potrebbero essere le modifiche rispetto a 3 commit fa, oppure
  •   
  • potrebbe essere solo un commit specifico.
  •   
  • L'utente potrebbe voler sottoporre tali inversioni a file specifici ,
  •   

(eg revert è documentato qui , ma io sono non sono sicuro che faccia parte dell'attuale distribuzione di es. però)

  

ma tutto si riduce a " ripristinando le modifiche " alla fine.

eg revert --since HEAD~3  # Undo all changes since HEAD~3
eg revert --in HEAD~8     # much like git revert HEAD~8, but nocommit by default
eg revert --since HEAD foo.py  # Undo changes to foo.py since last commit
eg revert foo.py               # Same as above
eg revert --in trial~7 bar.c baz.  # Undo changes made in trial~7 to bar.[ch]
  

Sono questi tipi di " ripristino dei dati " davvero così diversi che dovrebbero essere necessari comandi diversi o che alcune di queste operazioni non dovrebbero essere supportate dal semplice comando di ripristino?
  Certo, la maggior parte degli utenti utilizzerà probabilmente il & Quot; eg revert FILE1 FILE2... & Quot;   modulo, ma non ho riscontrato danni nel supportare le funzionalità extra.

     

Inoltre ... c'è qualcosa di fondamentale che impedirebbe al core git di adottare un simile comportamento?

     

Elia

     

Nota: i commit di default non hanno senso per il comando revert generalizzato e " git revert REVISION " farebbe un errore con le istruzioni (dicendo all'utente di aggiungere il --in flag).


Supponiamo che, su 50 di commit, 20 file ti rendano conto che il vecchio commit X ha introdotto modifiche che non avrebbero dovuto aver luogo.
Un piccolo impianto idraulico è in ordine.
Ciò di cui hai bisogno è un modo per elencare tutti i file specifici necessari per ripristinare
(come in " per annullare le modifiche apportate in commit X mantenendo tutte le modifiche successive " ),
e poi, per ciascuno di essi:

git-merge-file -p a.py X X^

Il problema qui è recuperare la funzione persa senza cancellare tutte le successive modifiche in a.py che potresti voler mantenere.
Quella tecnica viene talvolta chiamata & Quot; fusione negativa & Quot ;.

Dal git merge-file <current-file> <base-file> <other-file> significa :
incorpora tutte le modifiche che portano da <base-file> a <other-file> in <current-file>, puoi ripristinare la funzione eliminata dicendo che vuoi incorporare tutte le modifiche.)

  • da: X (dove la funzione è stata eliminata)
  • a: X ^ (il precedente commit prima di X, dove la funzione era ancora lì)

Nota: l'argomento '-p' che ti consente di rivedere prima le modifiche senza fare nulla sulla curfile di noleggio. Quando sei sicuro, rimuovi quell'opzione.

Nota : il git merge-file è non così semplice : non puoi fare riferimento a versioni precedenti del file in questo modo.
(avrai ripetutamente il messaggio frustrante: error: Could not stat X )
Devi:

git cat-file blob a.py > tmp/ori # current file before any modification
git cat-file blob HEAD~2:a.py > tmp/X # file with the function deleted
git cat-file blob HEAD~3:a.py > tmp/F # file with the function which was still there

git merge-file a.py tmp/X tmp/F # basically a RCS-style merge
                                 # note the inversed commit order: X as based, then F
                                 # that is why is is a "negative merge"
diff -u a.py tmp/ori # eyeball the merge result
git add a.py 
git commit -m "function restored" # and any other changes made from X are preserved!

Se questo deve essere fatto per un gran numero di file all'interno di un precedente commit ... alcuni script sono in ordine;)

Per ripristinare le modifiche in un solo file all'interno di un commit, come VonC ha sottolineato, vorrei checkout il ramo (master o trunk o altro) e quindi diff la versione del file che volevo ripristinare e trattarlo come un nuovo commit:

$ git checkout trunk
$ git checkout 4f4k2a^ a.py
$ git add a.py
$ git diff              #verify I'm only changing what I want; edit as needed
$ git commit -m 'recover function deleted from a.py in 4f4k2a'

Probabilmente c'è un comando idraulico che lo farebbe direttamente, ma non lo userei se lo sapessi. Non è che non mi fido di Git, ma non mi fido di me stesso - non mi fiderei di sapere senza aver visto cosa è cambiato in quel file in quel commit e da allora. E una volta guardato, è più semplice creare un nuovo commit modificando <=>. Forse è solo uno stile di lavoro personale.

Dai un'occhiata a questo ritorno git domanda . Sembra esserci un problema che ripristina i commit più vecchi se non in una sequenza consecutiva incluso il commit più recente.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top