Por que existem 2 maneiras de abrir um arquivo no git?
Às vezes o git sugere git rm --cached
para abrir um ficheiro, às vezes git reset HEAD file
. Quando devo usar o quê?
editar:
D:\code\gt2>git init
Initialized empty Git repository in D:/code/gt2/.git/
D:\code\gt2>touch a
D:\code\gt2>git status
# On branch master
#
# Initial commit
#
# Untracked files:
# (use "git add <file>..." to include in what will be committed)
#
# a
nothing added to commit but untracked files present (use "git add" to track)
D:\code\gt2>git add a
D:\code\gt2>git status
# On branch master
#
# Initial commit
#
# Changes to be committed:
# (use "git rm --cached <file>..." to unstage)
#
# new file: a
#
D:\code\gt2>git commit -m a
[master (root-commit) c271e05] a
0 files changed, 0 insertions(+), 0 deletions(-)
create mode 100644 a
D:\code\gt2>touch b
D:\code\gt2>git status
# On branch master
# Untracked files:
# (use "git add <file>..." to include in what will be committed)
#
# b
nothing added to commit but untracked files present (use "git add" to track)
D:\code\gt2>git add b
D:\code\gt2>git status
# On branch master
# Changes to be committed:
# (use "git reset HEAD <file>..." to unstage)
#
# new file: b
#
10 answers
git rm --cached <filePath>
não remove um ficheiro, na verdade Escalona a remoção do(s) ficheiro (s) do repo (assumindo que já foi cometido antes), mas deixa o ficheiro na sua árvore de trabalho (deixando-o com um ficheiro sem rasto).
git reset -- <filePath>
will unstage quaisquer alterações escalonadas para o(s) ficheiro (s) indicado (s).
git rm --cached
em um novo arquivo que é encenado, basicamente pareceria que você tinha acabado de soltá-lo, uma vez que ele nunca tinha sido cometido antes.
git rm --cached
é usado para remover um arquivo do Índice. No caso em que o arquivo já está no repo, git rm --cached
irá remover o arquivo do Índice, deixando-o no diretório de trabalho e um commit irá agora removê-lo do repo também. Basicamente, após o commit, você teria desapertado o arquivo e mantido uma cópia local.
git reset HEAD file
( que por padrão está usando a bandeira --mixed
é diferente no caso em que o arquivo já está no repo, ele substitui a versão de índice de o arquivo com o do repo (HEAD), efetivamente liberando as modificações para ele.
No caso de arquivo sem Versão, ele vai desatar o arquivo inteiro como o arquivo não estava lá na cabeça. Neste aspecto git reset HEAD file
e git rm --cached
são os mesmos, mas não são os mesmos ( como explicado no caso de arquivos já no repo)
Muito simplesmente:
-
git rm --cached <file>
faz com que o git pare de seguir o ficheiro completamente (deixando-o no sistema de Ficheiros, ao contrário do simplesgit rm
*) -
git reset HEAD <file>
remove todas as modificações feitas no ficheiro desde o último commit (mas não as reverte no sistema de Ficheiros, ao contrário do que o nome do comando possa sugerir**). O arquivo permanece sob controle de revisão.
Se o ficheiro não estava no controlo de revisões antes (ou seja, está a desbloquear um ficheiro que você tinha apenas git add
ed pela primeira vez), então os dois comandos têm o mesmo efeito, daí o aparecimento destes ser "duas maneiras de fazer algo".
* tenha em mente a caveat @DrewT menciona em sua resposta, a respeito de git rm --cached
de um arquivo que foi previamente comprometido para o repositório. No contexto desta questão, de um arquivo apenas adicionado e ainda não comprometido, não há nada com que se preocupar.
** fiquei com medo durante muito tempo. o comando git reset por causa de seu nome -- e ainda hoje eu frequentemente procuro a sintaxe para me certificar de que não faço asneira. (update : finalmente tive tempo para resumir o uso de git reset
numa página do tldr , por isso agora tenho um modelo mental melhor de como funciona, e uma referência rápida para quando me esqueço de algum detalhe.)
Este tópico é um pouco velho, mas eu ainda quero adicionar um pouco de demonstração uma vez que ainda não é um problema intuitivo:
me$ git status
# On branch master
# Changes to be committed:
# (use "git reset HEAD <file>..." to unstage)
#
# new file: to-be-added
# modified: to-be-modified
# deleted: to-be-removed
#
me$ git reset -q HEAD to-be-added
# ok
me$ git reset -q HEAD to-be-modified
# ok
me$ git reset -q HEAD to-be-removed
# ok
# or alternatively:
me$ git reset -q HEAD to-be-added to-be-removed to-be-modified
# ok
me$ git status
# On branch master
# Changes not staged for commit:
# (use "git add/rm <file>..." to update what will be committed)
# (use "git checkout -- <file>..." to discard changes in working directory)
#
# modified: to-be-modified
# deleted: to-be-removed
#
# Untracked files:
# (use "git add <file>..." to include in what will be committed)
#
# to-be-added
no changes added to commit (use "git add" and/or "git commit -a")
git reset HEAD
(Sem -q
) dá um aviso sobre o arquivo modificado e seu código de saída é 1 que será considerado como um erro em um script.
Editar: git checkout HEAD to-be-modified to-be-removed
também funciona para o 'unstaging', mas remove a mudança completamente do espaço de trabalho
Se tiver encenado acidentalmente ficheiros que não gostaria de enviar, e quiser ter a certeza de que mantém as alterações, também pode usar:
git stash
git stash pop
Isto efectua um reset à cabeça e volta a aplicar as suas alterações, permitindo-lhe reestabelecer os ficheiros individuais para a persistência. isto também é útil se você se esqueceu de criar um ramo de recursos para pedidos de pull (git stash ; git checkout -b <feature> ; git stash pop
).
Estes 2 comandos têm várias diferenças subtis se o ficheiro em questão já estiver no repo e sob controlo de versão (anteriormente comprometido, etc.):
-
git reset HEAD <file>
desvia o ficheiro na persistência actual. -
git rm --cached <file>
irá abrir o ficheiro para os commits futuros também. É instável até ser adicionado novamente comgit add <file>
.
- Depois de correr {[[1] } e empurrar o seu ramo para o comando, qualquer um puxando a sua ramificação do remoto irá obter o ficheiro realmente apagado da sua pasta, mesmo que no seu conjunto de trabalho local o ficheiro fique sem rasto (ou seja, não fisicamente apagado da pasta).
Esta última diferença é importante para os projectos que incluem um ficheiro de configuração em que cada programador da equipa tem uma configuração diferente (isto é, uma configuração diferente de url de base, ip ou porto) por isso, se estiver a usar git rm --cached <file>
Qualquer pessoa que puxe a sua ramificação terá de recriar manualmente a configuração, ou você pode enviar-lhes o seu e eles podem re-editá-lo de volta para suas configurações de ip (etc.), porque o delete apenas efeitos pessoas puxando seu ramo do controle remoto.
Digamos que você stage
uma pasta inteira via git add <folder>
, mas você quer excluir um ficheiro da lista encenada (ou seja, a lista que gera ao executar git status
) e manter as modificações dentro do ficheiro excluído (você estava a trabalhar em algo e não está pronto para cometer, mas não quer perder o seu trabalho...). Você poderia simplesmente usar:
git reset <file>
Quando você executar git status
, você verá que qualquer arquivo que você reset
são unstaged
e o resto dos arquivos que você added
ainda estão na lista.
1.
D:\code\gt2>git status
# On branch master
#
# Initial commit
#
# Changes to be committed:
# (use "git rm --cached <file>..." to unstage)
#
# new file: a
(use " git rm --Cache ..."para soltar)
Git é um sistema de ponteiros
Você não tem um commit ainda para mudar o seu ponteiro para
A única maneira de 'tirar os ficheiros do balde que está a ser apontado' é para remover os ficheiros que disse ao git para vigiar as alterações
2.
D:\code\gt2>git commit -m a
[master (root-commit) c271e05] a
0 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 a
Git commit-m a
- tu vieste, 'salvo'
3.
D:\code\gt2>git status
# On branch master
# Changes to be committed:
# (use "git reset HEAD <file>..." to unstage)
#
# new file: b
#
(use " git reset HEAD ..."para soltar)
- fizeste um commit no teu código neste momento
- Agora você pode reiniciar o seu cursor para o seu commit 'volte para a última gravação'
# git reflog
<find the place before your staged anything>
# git reset HEAD@{1}
O reflog é um histórico git que não só acompanha as alterações ao repo, mas também acompanha as acções do utilizador (por exemplo. pull, checkout para branch diferente, etc) e permite desfazer essas ações. Então, em vez de desamarrar o arquivo que foi mal encenado, onde você pode reverter para o ponto onde você não encenou os arquivos.
Isto é semelhante a git reset HEAD <file>
mas em certos casos pode ser mais granular.
Parece-me que git rm --cached <file>
remove o ficheiro do Índice sem o remover do directório onde um plain git rm <file>
faria ambas as coisas, tal como um OS rm <file>
removeria o ficheiro do directório sem remover a sua versionagem.