Omylem jsem přidal soubory do příkazu git pomocí příkazu:
git add myfile.txt
git commit
jsem ještě nespustil. Existuje způsob, jak to vrátit, takže tyto soubory nebudou zahrnuty do odevzdání?
Dosud existuje 48 odpovědí (některé vypuštěny). Nepřidávejte nové, pokud nemáte nějaké nové informace.
Před potvrzením pomocí příkazu git add
můžete vrátit zpět
git reset <file>
který ji odstraní z aktuálního indexu (seznam "o tom, že bude spáchán"), aniž by změnil cokoli jiného.
Můžeš použít
git reset
bez jakéhokoliv názvu souboru, chcete-li zrušit všechny příslušné změny. To se může hodit, když je příliš mnoho souborů, které mají být v rozumném množství uvedeny jeden po druhém.
Ve starých verzích Gitu jsou výše uvedené příkazy ekvivalentní s git reset HEAD <file>
a git reset HEAD
a nezdaří, pokud je HEAD
nedefinováno (protože jste ještě neučinili žádné závazky ve vašem repo) nebo dvojznačné (protože jste vytvořili větev nazvanou HEAD
, která je hloupá věc, kterou byste neměli dělat. Tento byl změněn v Git 1.8.2 , nicméně, v moderních verzích Gitu můžete použít příkazy výše i před provedením vašeho prvního potvrzení:
"git reset" (bez možností nebo parametrů) slouží k chybě, když nemáte ve vaší historii žádné potvrzení, ale nyní vám dává prázdný index (aby odpovídaly neexistujícímu potvrzení, že nejste ani zapnuti).
Ty chceš:
git rm --cached <added_file_to_undo>
Uvažování:
Když jsem k tomu byla nová, snažila jsem se
git reset .
(chcete-li vrátit zpět celé své počáteční přidání), pouze pro získání této (ne) užitečné zprávy:
fatal: Failed to resolve 'HEAD' as a valid ref.
Ukazuje se, že je to proto, že HEAD ref (větev?) Neexistuje až po prvním potvrzení. To znamená, že narazíte na stejný problém začátečníka jako já, pokud váš pracovní postup, jako je můj, byl něco jako:
git init
git add .
git status
... spousta svinutí kecy ...
=> Sakra, nechtěla jsem to všechno přidat.
google "přidat zpět"
=> najít přetečení zásobníku - yay
git reset .
=> fatal: Nepodařilo se vyřešit 'HEAD' jako platné ref.
Dále se ukáže, že je chyba zaprotokolována proti neužitečnosti v seznamu adresátů.
A že správné řešení bylo právě ve výstupním stavu Git (což jsem přece jen označil za „blbost“)
... # Changes to be committed: # (use "git rm --cached <file>..." to unstage) ...
A řešením je skutečně použití git rm --cached FILE
.
Všimněte si varování jinde - git rm
vymaže místní pracovní kopii souboru, ale ne pokud používáte --cached . Výsledek git help rm
:
--cached Tato volba slouží k odpojení a odstranění cest pouze z indexu. Pracovní stromové soubory, ať už upravené nebo ne, budou ponechány.
I nadále používat
git rm --cached .
odstranit vše a začít znovu. Nefungovalo však, protože zatímco add .
je rekurzivní, ukazuje rm
potřeby -r
k recitaci. Povzdech.
git rm -r --cached .
Dobře, teď jsem zpátky tam, kde jsem začal. Příště budu používat -n
na suché běh a uvidím, co bude přidáno:
git add -n .
Zapamatoval jsem si vše na bezpečné místo před důvěřováním git help rm
o --cached
, které nic nezničí (a co když jsem to chybně napsal).
Pokud zadáte:
git status
git vám řekne, co je inscenováno, atd., včetně instrukcí, jak postupovat:
use "git reset HEAD <file>..." to unstage
Zjistil jsem, že git dělá docela dobrou práci, že mě to nutí dělat správné věci v takovýchto situacích.
Poznámka: Poslední verze git (1.8.4.x) tuto zprávu změnily:
(use "git rm --cached <file>..." to unstage)
Pro objasnění: git add
přesune změny z aktuálního pracovního adresáře do pracovní oblasti (index).
Tento proces se nazývá staging . Takže nejpřirozenější příkaz do fáze změny (změněné soubory) je zřejmý:
git stage
git add
je jen jednodušší alias pro git stage
Škoda, že neexistuje žádné git unstage
ani git unadd
příkazy. Příslušný je těžší uhodnout nebo si pamatovat, ale je zcela zřejmý:
git reset HEAD --
Pro tento účel můžeme snadno vytvořit alias:
git config --global alias.unadd 'reset HEAD --'
git config --global alias.unstage 'reset HEAD --'
A konečně máme nové příkazy:
git add file1
git stage file2
git unadd file2
git unstage file1
Osobně používám i kratší aliasy:
git a #for staging
git u #for unstaging
Kromě přijaté odpovědi, pokud byl váš omylem přidaný soubor obrovský, pravděpodobně si všimnete, že i po jeho odstranění z indexu s 'git reset
' se stále zdá, že zabírá místo v adresáři .git
. To není nic, čeho by se mělo bát, soubor je stále ještě v úložišti, ale pouze jako "volný objekt", nebude kopírován do jiných repozitářů (přes klon, Push) a prostor bude nakonec rekultivován - i když možná ne příliš brzy. Pokud jste nervózní, můžete spustit:
git gc --Prune=now
Aktualizace (následuje můj pokus o odstranění nějakého zmatku, který může vyplynout z nejvíce odhlasovaných odpovědí):
Takže, což je reálné undo of git add
?
git reset HEAD <file>
?
nebo
git rm --cached <file>
?
Přísně vzato, a pokud se nemýlím: žádný .
git add
nemůže být vráceno - bezpečně, obecně.
Připomeňme si nejprve, co vlastně git add <file>
dělá:
Pokud <file>
bylo nebylo dříve sledováno , git add
přidá jej do cache , s jeho aktuálním obsahem.
Pokud bylo <file>
již sledováno , git add
uloží aktuální obsah (snímek, verze) do mezipaměti. V GIT se tato akce stále nazývá add , (ne pouhá update it), protože dvě různé verze (snímky) souboru jsou považovány za dvě různé položky: proto přidáváme skutečně novou položku do mezipaměti, která bude nakonec přijata později.
Vzhledem k tomu je otázka poněkud nejednoznačná:
Omylem jsem přidal soubory pomocí příkazu ...
Scénář OP se jeví jako první (nepozorovaný soubor), chceme, aby "undo" odstranil soubor (nejen aktuální obsah) ze sledovaných položek. Pokud je to tento případ, pak je v pořádku spustit git rm --cached <file>
.
Můžeme také spustit git reset HEAD <file>
. To je obecně vhodnější, protože funguje v obou scénářích: také dělá zpět, když jsme nesprávně přidali verzi již sledované položky.
Existují však dvě výhrady.
Za prvé: Existuje (jak je uvedeno v odpovědi) pouze jeden scénář, ve kterém git reset HEAD
nefunguje, ale git rm --cached
dělá: nový repozitář (bez povelů). Ale ve skutečnosti je to prakticky irelevantní případ.
Za druhé: Uvědomte si, že git reset HEAD
nemůže magicky obnovit dříve uložený obsah souboru, pouze jej znovu synchronizuje z HEAD. Pokud naše pomýlené git add
přepsalo předchozí zprovozněnou verzi, nemůžeme ji obnovit. Proto nemůžeme striktně hovořit [*].
Příklad:
$ git init
$ echo "version 1" > file.txt
$ git add file.txt # first add of file.txt
$ git commit -m 'first commit'
$ echo "version 2" > file.txt
$ git add file.txt # stage (don't commit) "version 2" of file.txt
$ git diff --cached file.txt
-version 1
+version 2
$ echo "version 3" > file.txt
$ git diff file.txt
-version 2
+version 3
$ git add file.txt # oops we didn't mean this
$ git reset HEAD file.txt # undo ?
$ git diff --cached file.txt # no dif, of course. stage == HEAD
$ git diff file.txt # we have lost irrevocably "version 2"
-version 1
+version 3
Samozřejmě, že to není příliš kritické, pokud dodržujeme obvyklý líný pracovní postup, který dělá 'git add' pouze pro přidávání nových souborů (případ 1), a aktualizujeme nový obsah příkazem commit, git commit -a
.
* (Edit: výše uvedené je prakticky správné, ale stále mohou existovat nějaké mírně hackerské/spletité způsoby, jak obnovit změny, které byly inscenovány, ale nebyly spáchány a poté přepsány - viz komentáře Johannesa Matokiče a iolsmit)
git rm --cached . -r
bude "un-add" vše, co jste přidali z aktuálního adresáře rekurzivně
Běh
git gui
a odstranit všechny soubory ručně nebo výběrem všech a kliknutím na tlačítko unstage z tlačítka commit .
Undo soubor, který již byl přidán, je poměrně snadné pomocí git , pro resetování myfile.txt
, které již bylo přidáno, použijte:
git reset HEAD myfile.txt
Vysvětlete:
Poté, co jste vytvořili nepotřebné soubory, vrátíte se zpět, můžete udělat git reset
, Head
je hlava vašeho souboru v lokálním souboru a poslední parametr je název vašeho souboru.
Kroky v níže uvedeném obrázku vytvořím podrobněji pro vás, včetně všech kroků, které mohou nastat v těchto případech:
Git má příkazy pro každou akci, kterou si lze představit, ale potřebuje rozsáhlé znalosti, aby se věci dostali správně, a proto je v nejlepším případě kontra-intuitivní ...
Co jste udělali dříve:
git add .
nebo git add <file>
.Co chceš:
Odstraňte soubor z indexu, ale ponechte jej ve verzi a ponechte s nezávaznými změnami v pracovní kopii:
git reset head <file>
Obnovit soubor do posledního stavu z HEAD, vrátit změny a odstranit je z indexu:
# Think `svn revert <file>` IIRC.
git reset HEAD <file>
git checkout <file>
# If you have a `<branch>` named like `<file>`, use:
git checkout -- <file>
To je nutné, protože git reset --hard HEAD
nebude fungovat s jednotlivými soubory.
Odebrat soubor <file>
z indexu a verzí a ponechat soubor bez verze se změnami v pracovní kopii:
git rm --cached <file>
Odebrat <file>
z pracovní kopie a verzí zcela:
git rm <file>
Otázka není jasně položena. Důvodem je to, že git add
má dva významy:
git rm --cached file
.git reset HEAD file
.v případě pochybností použijte
git reset HEAD file
Protože to dělá v obou případech očekávanou věc.
Upozornění: pokud uděláte git rm --cached file
na souboru, který byl upraven (soubor, který existoval dříve v úložišti), pak bude soubor odstraněn v souboru git commit
! Bude stále existovat ve vašem souborovém systému, ale pokud někdo jiný vytáhne váš závazek, soubor bude vymazán z jejich pracovního stromu.
git status
vám řekne, zda byl soubor nový soubor nebo upraven :
On branch master
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
new file: my_new_file.txt
modified: my_modified_file.txt
Pokud jste na svém počátečním potvrzení a nemůžete použít git reset
, stačí prohlásit "Git bankruptcy" a smazat složku .git
a začít znovu
Na mnoho dalších odpovědí můžete použít git reset
VUT:
Našel jsem tento skvělý post, který ve skutečnosti přidává příkaz Git (dobře alias) pro git unadd
: viz git unadd pro podrobnosti nebo ..
Jednoduše,
git config --global alias.unadd "reset HEAD"
Teď můžeš
git unadd foo.txt bar.txt
git remove
nebo git rm
může být použito pro tento účel pomocí příznaku --cached
. Snaž se:
git help rm
Použijte git add -i
k odstranění právě přidaných souborů z vašeho nadcházejícího potvrzení. Příklad:
Přidání souboru, který jste nechtěli:
$ git add foo
$ git status
# On branch master
# Changes to be committed:
# (use "git reset HEAD <file>..." to unstage)
#
# new file: foo
#
# Untracked files:
# (use "git add <file>..." to include in what will be committed)
# [...]#
Přechod do interaktivního přidávání pro vrácení vašeho přidání (příkazy zadané na stránce git zde jsou „r“ (vrátit se), „1“ (první položka v seznamu se vrátí k přehlídkám), „vrátit se“ a opustí režim vrácení a „q“ (přestat):
$ git add -i
staged unstaged path
1: +1/-0 nothing foo
*** Commands ***
1: [s]tatus 2: [u]pdate 3: [r]evert 4: [a]dd untracked
5: [p]atch 6: [d]iff 7: [q]uit 8: [h]elp
What now> r
staged unstaged path
1: +1/-0 nothing [f]oo
Revert>> 1
staged unstaged path
* 1: +1/-0 nothing [f]oo
Revert>>
note: foo is untracked now.
reverted one path
*** Commands ***
1: [s]tatus 2: [u]pdate 3: [r]evert 4: [a]dd untracked
5: [p]atch 6: [d]iff 7: [q]uit 8: [h]elp
What now> q
Bye.
$
A je to! Zde je váš důkaz, který ukazuje, že "foo" je zpět na seznamu nezaškrtnutých:
$ git status
# On branch master
# Untracked files:
# (use "git add <file>..." to include in what will be committed)
# [...]
# foo
nothing added to commit but untracked files present (use "git add" to track)
$
Zde je způsob, jak se vyhnout tomuto znepokojujícímu problému při spuštění nového projektu:
git init
.Git dělá to opravdu těžké dělat git reset
jestliže vy nemáte žádné závazky. Pokud vytvoříte drobný úvodní závazek jen kvůli tomu, abyste ho měli, pak můžete git add -A
a git reset
tolikrát, kolikrát chcete, aby bylo vše v pořádku.
Další výhodou této metody je, že pokud se později dostanete do problémů s koncem řádku a potřebujete aktualizovat všechny soubory, je to snadné:
Možná se od té doby, co jste odeslali svou otázku, vyvinula Git.
$> git --version
git version 1.6.2.1
Nyní můžete vyzkoušet:
git reset HEAD .
To by mělo být to, co hledáte.
Všimněte si, že pokud se vám nepodaří specifikovat revizi, musíte zahrnout oddělovač. Příklad z konzoly:
git reset <path_to_file>
fatal: ambiguous argument '<path_to_file>': unknown revision or path not in the working tree.
Use '--' to separate paths from revisions
git reset -- <path_to_file>
Unstaged changes after reset:
M <path_to_file>
(verze git 1.7.5.4)
Jak odstranit nové soubory z pracovní oblasti (a pouze v případě nového souboru), jak je uvedeno výše:
git rm --cached FILE
Použijte rm --cached pouze pro nové soubory omylem přidané.
Chcete-li obnovit všechny soubory v určité složce (a jejích podsložkách), můžete použít následující příkaz:
git reset *
použijte příkaz *
ke zpracování více souborů najednou
git reset HEAD *.prj
git reset HEAD *.bmp
git reset HEAD *gdb*
atd
Stačí zadat git reset
vrátí se zpět a je to jako byste nikdy nezadali git add .
od posledního potvrzení. Ujistěte se, že jste se dopustili.
Pro konkrétní soubor:
- git reset my_file.txt
- git checkout my_file.txt
Pro všechny přidané soubory:
- git reset.
- git checkout.
Poznámka: checkout změní kód v souborech a přesune se do posledního aktualizovaného stavu. reset nezmění kódy; pouze resetuje záhlaví.
Chcete-li vrátit zpět git, použijte
git reset filename
Tento příkaz odstraní změny:
git reset HEAD filename.txt
Můžete také použít
git add -p
přidat části souborů.
Jsem překvapen, že nikdo neuvádí interaktivní režim:
git add -i
vyberte možnost 3 pro přidání souborů. V mém případě často chci přidat více než jeden soubor, s interaktivní režim můžete použít čísla, jako je tento přidat soubory. Bude to trvat 4: 1,2,3,5
Chcete-li zvolit posloupnost, stačí zadat 1-5, aby se vše od 1 do 5.
git add myfile.txt
# toto přidá váš soubor do seznamu
Naproti tomuto příkazu je,
git reset HEAD myfile.txt # this will undo it.
takže budete v předchozím stavu. bude opět v seznamu nezaškrtnutých (předchozí stav).
bude resetovat hlavu s daným souborem. takže pokud to vaše hlava nemá, bude to jednoduše resetovat
git reset filename.txt
Odstraní soubor pojmenovaný filename.txt z aktuálního indexu, oblast "o tom, že bude spáchána", aniž by se změnilo cokoli jiného.
V SourceTree to můžete snadno udělat přes gui. Můžete zkontrolovat, který příkaz sourcetree používá k odpojení souboru.
Vytvořil (a) jsem nový soubor a přidal (a) do gitu. Pak jsem ho nestabilizoval pomocí SourceTree gui. To je výsledek:
Odstavení souborů [08/12/15 10:43]
git -c diff.mnemonicprefix = false -c core.quotepath = false -c credential.helper = sourcetree reset -q - cesta/do/souboru/filename.Java
SourceTree používá reset
k odpojení nových souborů.
git reset filename.txt
Odstraní soubor pojmenovaný filename.txt z aktuálního indexu, oblast "o tom, že bude spáchána", aniž by se změnilo cokoli jiného.
Jedním z nejintuitivnějších řešení je použití SourceTree .
Můžete pouze přetahovat soubory z inscenovaných a nestabilních souborů
Příkaz git reset
vám pomůže modifikovat pracovní oblast nebo pracovní oblast a pracovní strom. Schopnost Gitu řemeslně se dopustit přesně takového, jaký chcete, znamená, že budete někdy muset vrátit změny změn, které jste provedli pomocí programu git add.
Můžete to udělat voláním git reset HEAD <file to change>
. Máte dvě možnosti, jak se zcela zbavit změn. git checkout HEAD <file(s) or path(s)>
je rychlý způsob, jak vrátit změny do pracovní oblasti a pracovního stromu. S tímto příkazem buďte opatrní, protože odstraňuje všechny změny ve vašem pracovním stromu. Git o těchto změnách neví, protože nikdy nebyly spáchány. Po spuštění tohoto příkazu není možné tyto změny vrátit zpět.
Další příkaz k dispozici je git reset --hard
. Je to stejně destruktivní pro váš pracovní strom - po jeho spuštění dojde ke ztrátě jakýchkoli nepotvrzených změn nebo provedených změn. Spuštění git reset -hard HEAD
provede totéž jako git checkout HEAD
. To prostě nevyžaduje soubor nebo cestu k práci.
Můžete použít --soft
s git reset
. Obnoví úložiště na vámi zadaný příkaz a provede všechny tyto změny. Změny, které jste již provedli, nejsou ovlivněny ani změny ve vašem pracovním stromu.
Nakonec můžete pomocí --mixed
obnovit pracovní strom bez provedení jakýchkoli změn. To také unstages všechny změny, které jsou uvedeny.