"Git rm --cached x" vs "git reset head - x"?

163

GitRef.org - Básico :

git rmremoverá entradas da área de preparação. Isso é um pouco diferente dos git reset HEADarquivos "unstages". Por "instável", quero dizer que reverte a área de preparação para o que estava lá antes de começarmos a modificar as coisas. git rmpor outro lado, apenas retira o arquivo do palco completamente, para que não seja incluído no próximo instantâneo de confirmação, excluindo-o efetivamente.

Por padrão, a git rm fileremoverá o arquivo inteiramente da área de armazenamento temporário e também fora do seu disco> (o diretório de trabalho). Para deixar o arquivo no diretório de trabalho, você pode usar git rm --cached.

Mas qual é exatamente a diferença entre git rm --cached asde git reset head -- asd?

Pacerier
fonte

Respostas:

219

Existem três lugares onde um arquivo, digamos, pode estar - a árvore, o índice e a cópia de trabalho. Ao adicionar um arquivo a uma pasta, você o adiciona à cópia de trabalho.

Quando você faz algo como git add filevocê o adiciona ao índice. E quando você o confirma, você o adiciona à árvore também.

Provavelmente, ajudará você a conhecer os três sinalizadores mais comuns no git reset:

git reset [- <mode>] [ <commit>]

Este formulário redefine o cabeçalho de ramificação atual para <commit>e possivelmente atualiza o índice (redefinindo-o para a árvore de <commit>) e a árvore de trabalho, dependendo da <mode>que deve ser uma das seguintes opções :
--soft

Não toca no arquivo de índice nem na árvore de trabalho (mas redefine o cabeçalho para <commit>, como todos os modos). Isso deixa todos os seus arquivos alterados "Alterações a serem confirmadas", como o status do git colocaria.

--misturado

Redefine o índice, mas não a árvore de trabalho (ou seja, os arquivos alterados são preservados, mas não marcados para confirmação) e relata o que não foi atualizado. Esta é a ação padrão.

--Difícil

Redefine o índice e a árvore de trabalho. Quaisquer alterações nos arquivos rastreados na árvore de trabalho desde então <commit>são descartadas.

Agora, quando você faz algo como git reset HEAD- o que você está realmente fazendo é git reset HEAD --mixede ele "redefinirá" o índice para o estado em que estava antes de começar a adicionar arquivos / adicionar modificações ao índice (via git add) Nesse caso, a cópia de trabalho e o O índice (ou teste) estava sincronizado, mas você fez com que o HEAD e o índice estivessem sincronizados após a redefinição.

git rmpor outro lado, remove um arquivo do diretório ativo e do índice e, quando você confirma, o arquivo também é removido da árvore. git rm --cachedno entanto, remove o arquivo do índice sozinho e o mantém em sua cópia de trabalho. Esse é exatamente o oposto de git add file Neste caso, você transformou o índice em diferente do HEAD e do trabalho, pois o HEAD possui a versão do arquivo confirmada anteriormente, a cópia de trabalho teve a última modificação, se houver, ou o conteúdo de HEAD de o arquivo e você removeu o arquivo do índice. Uma confirmação agora sincronizará o índice e a árvore e o arquivo será removido.

manojlds
fonte
Percebo que após git rm --cachedo git diffcomando não mostra nenhum diff, mas git diff --cachedmostra o diff, como se ainda estivesse em cache. No git statusentanto, mostra o arquivo como sendo Untracked. Parece meio inconsistente.
haridsv
7
Não importa ... eu deveria ter usado git reset --mixed. Fiquei um pouco confuso com a afirmação que git rm --cachedé o oposto de git add. Tomada literalmente, está incorreta e pode causar danos. No meu caso, eu costumava git addadicionar um arquivo modificado à área de teste e queria o oposto de "that add" e não a adição inicial do arquivo. + A resposta de Greg Hewgill me ajudou a obter uma imagem mais clara.
haridsv
12
Acho o uso de cópia de trabalho, árvore e árvore de trabalho um pouco confuso. A árvore de trabalho é a cópia de trabalho ou a árvore?
Nealv 23/09
3
Como @haridsv mencionou, dizer git rm --cached'é exatamente o oposto de git add file' é enganoso. git reset fileestá mais perto de ser o oposto de git add file.
Matt Browne
@Nealv tardio, mas para outros que encontrarem este segmento: cópia de trabalho, árvore e árvore de trabalho, todos se referem à mesma coisa (no contexto do git).
De Novo
83

Talvez um exemplo ajude:

git rm --cached asd
git commit -m "the file asd is gone from the repository"

versus

git reset HEAD -- asd
git commit -m "the file asd remains in the repository"

Observe que, se você não alterou mais nada , o segundo commit não fará nada.

Greg Hewgill
fonte
3
Você pode me dizer o que esse hífen duplo - depois de HEAD realmente significa?
yuva
30
@yuva: --É usado para separar as opções de comando dos nomes dos arquivos. Se houvesse uma ramificação e um arquivo nomeados asd, git reset HEAD asdseria ambíguo. O --diz "tudo seguindo este é um nome de arquivo".
Greg Hewgill
É git reset HEAD <file>exatamente o mesmo que git rm --cached <file>e então git add --intent-to-add <file>?
álcool é mau
1
@alcoholisevil no, exceto em um caso especial. Veja esta resposta excelente e sucinta.
De Novo
45

git rm --cached fileirá remover o arquivo do palco. Ou seja, quando você confirmar o arquivo será removido. git reset HEAD -- filesimplesmente redefinirá o arquivo na área de teste para o estado em que estava no commit HEAD, ou seja, desfará todas as alterações feitas nele desde o último commit. Se essa alteração estiver adicionando o arquivo recentemente, elas serão equivalentes.

yuriks
fonte
7
Em conjunto com a noção (como mencionado em outras respostas) que git rm --cached fileé meio oposta git add, essa resposta fez muito sentido para mim e foi bem sucinta. Quase tão curto quanto esse comentário;)
rbatt
2
@ rbatt apenas para colocar o comentário aqui também, e esclarecer, git rm --cached filenão é o oposto degit add file . O comportamento passa a ser o oposto git add fileno caso específico em que você adicionou um novo arquivo anteriormente não rastreado. Em qualquer outro caso, o oposto de git add fileé git reset HEAD file. git reset HEAD filetambém reverte git add fileno primeiro caso (adicionando um arquivo não rastreado) e, em todos os casos, é por isso que o git sugere fazer se você deseja reverter um add do git.
De Novo