Rimuovi i file da Git commit


1613

Sto usando Git e ho commesso alcuni file usando

git commit -a

Successivamente, ho scoperto che un file era stato erroneamente aggiunto al commit.

Come posso rimuovere un file dall'ultimo commit?


2
Questo collegamento è perfetto per la tua domanda: stackoverflow.com/questions/307828/...
b3h3m0th

@CharlesB: sì, questo è il mio ultimo commit
Lolly

8
hai inviato il commit al server?
Paritosh Singh,

4
Lo faccio solo usando:git reset filepath
felipekm il

Risposte:


3090

Penso che altre risposte qui siano sbagliate, perché si tratta di spostare i file commessi per errore nell'area di gestione temporanea dal commit precedente, senza annullare le modifiche apportate. Questo può essere fatto come suggerito da Paritosh Singh:

git reset --soft HEAD^ 

o

git reset --soft HEAD~1

Quindi reimpostare i file indesiderati per lasciarli fuori dal commit:

git reset HEAD path/to/unwanted_file

Ora esegui nuovamente il commit, puoi persino riutilizzare lo stesso messaggio di commit:

git commit -c ORIG_HEAD  

86
Grazie per questo. Vale la pena aggiungere che se hai già inviato il tuo commit precedente (sbagliato) e ora provi a git pushcorreggere il tuo repository, si lamenterà Updates were rejected because the tip of your current branch is behind its remote counterpart.. Se sei sicuro di voler spingerli (ad es. È la tua forcella), puoi usare l' -fopzione per forzare la spinta, ad es git push origin master -f. (Non eseguire questa operazione in un repository upstream da cui altri stanno recuperando)
Andy Magoon,

57
git reset --soft HEAD^è la mia operazione di annullamento più comune
funroll

2
@PabloFernandez, prima di tutto, la risposta accettata avrebbe potuto essere ciò che l'OP stava cercando (inoltre, è stato pubblicato mesi prima). In secondo luogo, le risposte accettate sono sempre in primo piano, indipendentemente dal numero di voti positivi.
MITjanitor

4
@PabloFernandez nella parte superiore di tutte le risposte sono tre schede che ti consentono di controllare l'ordinamento delle risposte: attivo , meno recente e voti . Suppongo che il tuo sia impostato su più vecchio . Passa ai voti anche se la risposta accettata sarà ancora in alto, questa risposta sarà seconda.
ahsteele,

15
Ne sapevo molto, git resetma volevo un modo per influenzare il commit esistente "sul posto". Ho appena saputo git commit -C. Quindi per me, quello che voglio è la tua ricetta esatta con un altro passo, il "nuovo impegno di nuovo" spiegato come git commit -C [hash of original HEAD commit from first step].
metamatt

323

ATTENZIONE ! Se vuoi solo rimuovere un file dal tuo precedente commit e tenerlo su disco , leggi la risposta di juzzlin appena sopra.

Se questo è il tuo ultimo commit e desideri eliminare completamente il file dal tuo repository locale e remoto , puoi:

  1. rimuovere il file git rm <file>
  2. impegnarsi con flag di modifica: git commit --amend

Il flag di modifica dice a git di eseguire nuovamente il commit, ma "unisci" (non nel senso di unire due rami) questo commit con l'ultimo commit.

Come indicato nei commenti, usare git rmqui è come usare il rmcomando stesso!


120
puoi anche usare git rm --cachedper mantenere i file su disco
Arkadiy Kukarkin il

14
Avvertimento per coloro che stanno esplorando questa risposta: assicurati di voler eliminare il file (come se non ci sia più!), Non semplicemente rimuoverlo dall'elenco Commit.
Scott Biggs,

8
Per aggiungere a quello che dicono gli altri (e per rendere più facile da ricordare di non farlo a meno che non si vuole veramente): L' rmnel gitcomando di sta facendo quello rmsé!
yo

@CharlesB Puoi per favore aggiungere la nota del commento di Arkadiy Kukarkin alla tua risposta per dargli maggiore visibilità?
mopo922,

2
Nota che i file possono ancora essere ripristinati, nel caso in cui tu abbia cambiato idea, il commit precedente git commit --amendè ancora lì e può essere trovato ad esempio con git reflog. Quindi non è così male come suggeriscono gli altri commenti.
Steohan,

165

Le risposte esistenti parlano tutte della rimozione dei file indesiderati dall'ultimo commit.

Se si desidera rimuovere file indesiderati da un vecchio commit (anche push) e non si desidera creare un nuovo commit, che non è necessario, a causa dell'azione:

1.

Trova il commit a cui desideri che il file sia conforme.

git checkout <commit_id> <path_to_file>

puoi farlo più volte se vuoi rimuovere molti file.

2.

git commit -am "remove unwanted files"

3.

Trova il commit_id del commit su cui i file sono stati aggiunti per errore , diciamo "35c23c2" qui

git rebase 35c23c2~1 -i  // notice: "~1" is necessary

Questo comando apre l'editor in base alle tue impostazioni. Quello predefinito è vim.

Spostare l'ultimo commit, che dovrebbe essere "rimuovi file indesiderati", sulla riga successiva del commit errato ("35c23c2" nel nostro caso) e impostare il comando come fixup:

pick 35c23c2 the first commit
fixup 0d78b28 remove unwanted files

Dovresti essere bravo dopo aver salvato il file.

Finire :

git push -f

Se purtroppo si verificano conflitti, è necessario risolverli manualmente.


2
Farlo con nano è favoloso! Ctrl + K, Ctrl + U, metti una 'f', Ctrl + X, metti 'y' e voilà!
sequielo,

6
Se si desidera rimuovere effettivamente i file dal repository (non dal filesystem), anziché semplicemente ripristinarli a una versione precedente, invece di eseguire il passaggio 1 git rm --cached <file(s)>.
caloroso

2
Aspetta che puoi spostare i commit nel file interattivo-rebase a piacimento?
Dan Rosenstark,

2
Puoi assolutamente, ma potresti (o non puoi) avere conflitti.
Brian,

6
Questo processo potrebbe essere reso un po 'più semplice aggiungendo --fixup=35c23c2al git commitcomando. Ciò imposterà automaticamente il commit come correzione del commit richiesto e quindi non sarà necessario specificarlo nel rebase. Inoltre, se aggiungi --autosquashal git rebasecomando, git sposterà automaticamente il commit nella posizione corretta, quindi non devi fare nulla nel rebase interattivo - salva semplicemente il risultato (il che significa che non devi nemmeno -icontrassegnare, anche se mi piace usarlo comunque per assicurarmi che tutto appaia come mi aspetto).
Guss,

144

Come indica la risposta accettata, è possibile farlo ripristinando l'intero commit. Ma questo è un approccio piuttosto pesante.
Un modo più pulito per farlo sarebbe quello di mantenere il commit e rimuovere semplicemente i file modificati da esso.

git reset HEAD^ -- path/to/file
git commit --amend --no-edit

Il git resetprenderà il file come era nel precedente commit, e la fase è nell'indice. Il file nella directory di lavoro non è stato toccato.
Il git commitsarà poi impegnarsi e schiacciare l'indice nella corrente commesso.

Questo essenzialmente prende la versione del file che era nel commit precedente e lo aggiunge al commit corrente. Ciò non comporta alcuna variazione netta e quindi il file viene effettivamente rimosso dal commit.


5
Questa è una risposta molto migliore per la rimozione di un solo file, senza revisione dell'intero commit.
nimish,

Questo è esattamente lo stesso di questa risposta: D stackoverflow.com/a/27340569/1623984
ThatsAMorais

@ThatsAMorais infatti :-). Mi chiedo se questa domanda si sia fusa con un'altra, ed è per questo che non l'ho vista. O forse sono solo cieco. In entrambi i casi, penso di essere propenso a lasciarlo perché basato sui voti sembra essere più popolare (forse le persone preferiscono la risposta breve e diretta).
Patrick,

Certamente lascialo! :) Abbiamo avuto chiaramente l'idea giusta e lo scopo è di aiutare. Penso che la fusione sia una buona teoria.
ThatsAMorais il

Come si fa se si è già passati a un ramo su Github? Ho provato a spingere dopo aver fatto questa correzione e ho ricevuto il messaggio "Gli aggiornamenti sono stati rifiutati perché la punta del tuo ramo attuale è dietro suggerimento: la sua controparte remota."
Ollie Williams,

41

Se non è stato eseguito il push delle modifiche sul server, è possibile utilizzare

git reset --soft HEAD~1

Ripristinerà tutte le modifiche e tornerà a un commit indietro

Se hai apportato le modifiche, segui i passaggi indicati da @CharlesB


2
-1 git reset rimuove il file delle modifiche avvenute dall'area di gestione temporanea, qui la modifica è stata
eseguita

OK, ma terrò il mio downvote dal momento che non è quello che l'OP vuole :) scusa
CharlesB

ok va bene per me, ma perché l'avversario non lo vuole. Qual è il problema?
Paritosh Singh,

non è un grosso problema, ma perché l'OP vuole rimuovere il file indesiderato dall'ultimo commit e si reimposta sullo stato prima di eseguire il commit. devi ancora ripetere il commit.
Charles B

3
@Aris usa <git diff --cached> per vedere le modifiche
Paritosh Singh,

37

Rimuovere il file usando rm lo cancellerà!

Stai sempre aggiungendo a un commit in git piuttosto che rimuoverlo, quindi in questo caso riporta il file allo stato in cui si trovava prima del primo commit (potrebbe essere un'azione 'rm' di cancellazione se il file è nuovo) e quindi ripetere il commit e il file andrà.

Per riportare il file in uno stato precedente:

    git checkout <commit_id> <path_to_file>

o per riportarlo allo stato sul HEAD remoto:

    git checkout origin/master <path_to_file>

quindi modifica il commit e dovresti trovare il file scomparso dall'elenco (e non cancellato dal tuo disco!)


36
git checkout HEAD~ path/to/file
git commit --amend

1
Questo è il modo migliore per modificare l'ultimo commit, quello che non è stato inviato. Ciò ripristinerà le modifiche in un file, rimuovendo efficacemente quel file dall'ultimo commit.
Alex Bravo,

Anche questo ha cambiato il file. Come conservare le modifiche locali nel file?
theonlygusti,

29

Quanto segue rimuoverà in scena solo il file desiderato, che è ciò che l'OP ha chiesto.

git reset HEAD^ /path/to/file

Vedrai qualcosa di simile al seguente ...

Modifiche da impegnare: (utilizzare "git reset HEAD ..." per annullare la messa in scena)

modificato: / percorso / in / file

Modifiche non messe in scena per il commit: (usa "git add ..." per aggiornare ciò che verrà eseguito il commit) (usa "git checkout - ..." per scartare le modifiche nella directory di lavoro)

modificato: / percorso / in / file

  • "Modifiche da impegnare" è la versione precedente del file prima del commit. Sembrerà una cancellazione se il file non è mai esistito. Se si impegna questa modifica, ci sarà una revisione che ripristina la modifica nel file nel proprio ramo.
  • "Modifiche non messe in scena per il commit" è la modifica che hai eseguito il commit e lo stato corrente del file

A questo punto, puoi fare quello che vuoi sul file, come ripristinare una versione diversa.

Quando sei pronto a impegnarti:

git commit --amend -a

oppure (se hai in corso altre modifiche che non vuoi ancora impegnare)

git commit add /path/to/file
git commit --amend

3
La risposta di juzzlin è ottima, ma è eccessivo per disimpegnare l'intero commit quando desideri solo disimpegnare uno. La mancata messa in scena dell'intero commit può causare problemi se al momento in quel commit sono presenti modifiche non file ai file che non si desidera perdere.
ThatsAMorais il

27

Ti spiegherò con un esempio.
Sia A, B, C 3 commit successivi. Commit B contiene un file che non avrebbe dovuto essere eseguito il commit.

git log  # take A commit_id
git rebase -i "A_commit_ID" # do an interactive rebase
change commit to 'e' in rebase vim # means commit will be edited
git rm unwanted_file
git rebase --continue
git push --force-with-lease <branchName>    

Se il file specifico non è nell'ultimo o precedente commit, questo è il modo più elegante. Direi persino che è il modo più elegante in generale. Mi piace il rebasing interattivo.
bvgheluwe il

Per un singolo commit, nooppassa a edit [A_commit_ID]oe [A_commit_ID]
TamusJRoyce il

23

Puoi semplicemente provare.

git reset --soft HEAD~1

e creare un nuovo commit.

Tuttavia, esiste un fantastico software "gitkraken". che rende facile lavorare con git.


1
E solo per notare: dopo questo, faresti git commit --amendper avere la rimozione del file aggiornata nell'ultimo commit; e successivamente, puoi verificare che sia stato effettivamente rimosso congit log -1 --stat
sdbbs il

13
git rm --cached <file_to_remove_from_commit_<commit_id>_which_added_file>
git commit -m "removed unwanted file from git"

ti lascerà il file locale ancora. Se non vuoi neanche il file localmente, puoi saltare l'opzione --cached.

Se tutto il lavoro è sul tuo ramo locale, devi conservare il file in un commit successivo e, come avere una cronologia pulita, penso che un modo più semplice per farlo potrebbe essere:

git rm --cached <file_to_remove_from_commit_<commit_id>_which_added_file>
git commit --squash <commit_id>
git add <file_to_remove_from_commit_<commit_id>_which_added_file>
git commit -m "brand new file!"
git rebase --interactive <commit_id>^

e puoi quindi terminare il rebase con facilità senza dover ricordare comandi più complessi o eseguire il commit di messaggi o digitare altrettanto.


Questo funziona per me. Suppongo che se si desidera aggiungere nuovamente i file nel mix, basta usare git add -A o git add. e sono tornati.
Alexander Mills,

11

L'uso di git GUI può semplificare la rimozione di un file dal commit precedente.

Supponendo che questo non sia un ramo condiviso e non ti dispiaccia riscrivere la cronologia , quindi esegui:

git gui citool --amend

È possibile deselezionare il file commesso per errore e quindi fare clic su "Conferma".

inserisci qui la descrizione dell'immagine

Il file viene rimosso dal commit, ma verrà mantenuto sul disco . Quindi, se hai deselezionato il file dopo averlo erroneamente aggiunto, verrà visualizzato nell'elenco dei file non monitorati (e se hai deselezionato il file dopo averlo modificato erroneamente, verrà visualizzato nelle modifiche non messe in scena per l'elenco di commit).


2
Su Ubuntu, puoi installare git gui consudo apt-get install git-gui
JDiMatteo il

Grazie! Ero bloccato con un problema (bug?) In cui veniva aggiunta una cartella contenente un repository .git e tutti i normali comandi di rimozione non funzionavano. Questo comunque ha aiutato. Essendo un po 'indietro, l'ho usato prima git rebase -i HEAD~4e poi ho eseguito il tuo comando per aprire l'editor. Un'altra nota: "Unstaging" è disponibile nel menu "Commit".
Johny Skovdal,

La soluzione più semplice di tutte. Più semplice da ricordare E molto meno soggetto ad errori rispetto all'uso git reset --soft HEAD^(ricordando --soft arg), seguito da git commit -c ORIG_HEAD(piuttosto che --amend, che rovina tutto).
Brent Faust,

9

Se vuoi conservare il tuo commit (forse hai già trascorso un po 'di tempo a scrivere un messaggio di commit dettagliato e non vuoi perderlo), e vuoi solo rimuovere il file dal commit, ma non dal repository interamente:

git checkout origin/<remote-branch> <filename>
git commit --amend

6

Esegui una sequenza dei seguenti comandi:

//to remove the last commit, but preserve changes  
git reset --soft HEAD~1

//to remove unneded file from the staging area  
git reset HEAD `<your file>` 

//finally make a new commit  
git commit -m 'Your message'

Ho provato a fare questi passaggi e vedo questo errore: non è stato possibile inviare alcuni riferimenti a "git ...." Per evitare di perdere la cronologia, gli aggiornamenti non rapidi sono stati rifiutati Unisci le modifiche remote (ad es. 'git pull') prima di spingere di nuovo. Per i dettagli, consultare la sezione "Nota sui progressi rapidi" di "git push --help". (dopo git pull ho le stesse modifiche)
Dezigo,

Significa che lo stato del repository remoto è cambiato mentre svolgevi il lavoro locale. E dopo 'git pull' le tue modifiche locali dovrebbero essere unite a quelle remote, tutto qui. Naturalmente, le modifiche devono rimanere.
Sergey Onishchenko l'

In altre parole, se viene visualizzato l'errore @Dezigo, aggiungere il flag -f per forzare l'aggiornamento.
jungledev,

5

Volevo solo integrare la risposta migliore in quanto dovevo eseguire un comando aggiuntivo:

git reset --soft HEAD^
git checkout origin/master <filepath>

Saluti!


Benvenuto. Questa risposta sarebbe migliore se spiegassi cosa fanno effettivamente i comandi.
Mark Chorley,

3

Qualcosa che ha funzionato per me, ma penso ancora che ci dovrebbe essere una soluzione migliore:

$ git revert <commit_id>
$ git reset HEAD~1 --hard

Lascia la modifica che desideri annullare nell'altro commit, controlla gli altri

$ git commit --amend // or stash and rebase to <commit_id> to amend changes

3

git reset --soft HEAD^riavvolge il commit e quando digiti git statusti dice cosa fare:

Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

2

In realtà, penso che un modo più rapido e semplice sia usare la modalità interattiva git rebase.

git rebase -i head~1  

(o testa ~ 4, quanto lontano vuoi andare)

e poi, invece di 'pick', usa 'edit'. Non mi rendevo conto di quanto fosse potente "modifica".

https://www.youtube.com/watch?v=2dQosJaLN18

Spero che lo troverai utile.


il video
dura

2

Ho avuto lo stesso problema in cui ho apportato modifiche in una filiale locale in cui volevo ripristinare solo un file. Ciò che ha funzionato per me è stato -

( feature / target_branch di seguito è dove ho tutte le mie modifiche, comprese quelle che volevo annullare per un file specifico)

( origin / feature / target_branch è il ramo remoto in cui voglio inviare le mie modifiche)

( caratteristica / messa in scena è il mio ramo di gestione temporanea in cui spingerò da tutte le mie modifiche desiderate escludendo la modifica a quel file)

  1. Crea un ramo locale dalla mia origine / funzionalità / target_branch - chiamato funzione / messa in scena

  2. Ho unito la mia funzione di filiale locale funzionante / target_branch al ramo di funzionalità / stadiazione

  3. Il check-out caratteristica / staging poi ripristinato git ORIG_HEAD --soft (Ora tutte le modifiche dalla funzione / messa in scena' andrà in scena, ma non impegnati.)

  4. Non messo in scena il file che ho precedentemente archiviato con modifiche non necessarie

  5. Modificato il ramo upstream per feature / staging in origin / feature / target_branch

  6. Commesso il resto delle modifiche organizzate e spinto a monte verso la mia origine / funzione / target_branch remota


1

Se non hai più bisogno di quel file, puoi farlo

git rm file
git commit --amend
git push origin branch

1

Se stai usando GitHub e non hai ancora eseguito il commit, GitHub Desktop risolve facilmente questo problema:

  1. Scegli Repository -> Annulla il commit più recente
  2. Deseleziona il file che hai aggiunto per errore. Il tuo precedente messaggio di commit sarà già nella finestra di dialogo.
  3. Premi il pulsante Commit!

1

Se si desidera rimuovere file da precedenti commit utilizzare i filtri

git filter-branch --prune-empty --index-filter 'git rm --ignore-unmatch --cached "file_to_be_removed.dmg"'

Se vedi questo errore:

Impossibile creare un nuovo backup. Esiste già un backup precedente in refs / original / Force che sovrascrive il backup con -f

Basta rimuovere i backup refs sul repository locale

$ rm -rf .git/refs/original/refs

1

se non spingi ancora le tue modifiche su git

git reset --soft HEAD~1

Ripristinerà tutte le modifiche e tornerà a un commit indietro

Se questo è l'ultimo commit che hai fatto e vuoi eliminare il file dal repository locale e remoto prova questo:

git rm <file>
 git commit --amend

o anche meglio:

reimpostare prima

git reset --soft HEAD~1

reimpostare il file indesiderato

git reset HEAD path/to/unwanted_file

impegnarsi di nuovo

git commit -c ORIG_HEAD  

è come sopra ma ha anche aiutato davvero a fare un controllo incrociato
Reshma

0

Questo ha funzionato per me per rimuovere il file dal repo bit bucket che inizialmente ho spinto il file al ramo.

git checkout origin/develop <path-to-file>
git add <path-to-file>
git commit -m "Message"
git push

0

Ho copiato i file correnti in una cartella diversa, quindi mi sono liberato di tutte le modifiche non eliminate mediante:

git reset --hard @{u}

Quindi copiare le cose indietro. Impegni, spingi.


0

Puoi semplicemente usare questo comando:

git restore --staged <file>

0
Here is the step to remove files from Git Commit.

>git reset --soft HEAD^1(either commitid ) -- now files moved to the staging area.
>git rm --cached filename(it will removed the file from staging area)
>git commit -m 'meaningfull message'(Now commit the required files)

-1

Nessuna delle risposte in questo momento è ragionevole. Sembra che ci sia abbastanza richiesta per proporre una soluzione reale: https://github.com/git/git/blob/master/Documentation/SubmittingPatches

git --uncommit <nome file>

sarebbe bello. Capisco che non vogliamo modificare la cronologia, ma se sono locale e ho accidentalmente aggiunto il file locale "hack" locale e voglio rimuoverlo dal commit, ciò sarebbe di grande aiuto.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.