Eu li isso ao renomear arquivos no git , você deve confirmar quaisquer alterações, executar sua renomeação e depois preparar seu arquivo renomeado. O Git reconhecerá o arquivo a partir do conteúdo, em vez de vê-lo como um novo arquivo não rastreado, e manterá o histórico de alterações.
No entanto, fazendo exatamente isso esta noite, acabei revertendo para git mv
.
> $ git status
# On branch master
# Changes to be committed:
# (use "git reset HEAD <file>..." to unstage)
#
# modified: index.html
#
Renomeie minha folha de estilo no Finder de iphone.css
paramobile.css
> $ git status
# On branch master
# Changes to be committed:
# (use "git reset HEAD <file>..." to unstage)
#
# modified: index.html
#
# Changed but not updated:
# (use "git add/rm <file>..." to update what will be committed)
# (use "git checkout -- <file>..." to discard changes in working directory)
#
# deleted: css/iphone.css
#
# Untracked files:
# (use "git add <file>..." to include in what will be committed)
#
# css/mobile.css
Então o git agora acha que excluí um arquivo CSS e adicionei um novo. Não é o que eu quero, vamos desfazer a renomeação e deixar o git fazer o trabalho.
> $ git reset HEAD .
Unstaged changes after reset:
M css/iphone.css
M index.html
Voltar para onde eu comecei.
> $ git status
# On branch master
# Changes to be committed:
# (use "git reset HEAD <file>..." to unstage)
#
# modified: index.html
#
Vamos usar em seu git mv
lugar.
> $ git mv css/iphone.css css/mobile.css
> $ git status
# On branch master
# Changes to be committed:
# (use "git reset HEAD <file>..." to unstage)
#
# renamed: css/iphone.css -> css/mobile.css
#
# Changed but not updated:
# (use "git add <file>..." to update what will be committed)
# (use "git checkout -- <file>..." to discard changes in working directory)
#
# modified: index.html
#
Parece que estamos bem. Então, por que o git não reconheceu o nome da primeira vez que usei o Finder?
add+rm
oumv
- produz o mesmo resultado. O Git usa sua detecção de renomeação / cópia para que você saiba que foi uma renomeação. A fonte que você citou também é imprecisa. Realmente não importa se você modifica + renomear no mesmo commit ou não. Quando você faz uma diferença entre modificar e renomear, a detecção de renomeação será vista como uma renomeação + modificação, ou se a modificação for uma reescrita total, será exibida como adicionada e excluída - ainda não importa como você executou isto.git mv old new
atualiza automaticamente o índice. Ao renomear fora do Git, você precisará fazergit add new
egit rm old
realizar as alterações no índice. Depois de ter feito issogit status
funcionará como esperado.public_html
diretório, que é rastreado no git. Tendo realizadogit add .
egit commit
, ainda mostrou um monte de arquivos 'excluídos' nogit status
. Eu executei umgit commit -a
e as exclusões foram confirmadas, mas agora não tenho histórico nos arquivos que vivempublic_html
agora. Esse fluxo de trabalho não é tão bom quanto eu gostaria.Respostas:
Para
git mv
a página do manual dizPortanto, primeiro você deve atualizar o índice por conta própria (usando
git add mobile.css
). No entantogit status
, ainda mostrará dois arquivos diferentesVocê pode obter uma saída diferente executando
git commit --dry-run -a
, o que resulta no que você espera:Não sei dizer exatamente por que vemos essas diferenças entre
git status
egit commit --dry-run -a
, mas aqui está uma dica de Linus :A
dry-run
usa os mecanismos de renomeação reais, enquantogit status
provavelmente não.fonte
git add mobile.css
. Sem elegit status -a
, teria "visto" apenas a remoção doiphone.css
arquivo rastreado anteriormente, mas não teria tocado no novomobile.css
arquivo não rastreado . Além disso,git status -a
é inválido no Git 1.7.0 e posterior. "" Status git "não é mais" git commit --dry-run ".” em kernel.org/pub/software/scm/git/docs/RelNotes-1.7.0.txt . Usegit commit --dry-run -a
se você quiser essa funcionalidade. Como já foi dito, basta atualizar o índice egit status
funcionará como o OP espera.git commit
ele não confirmará o arquivo renomeado e a árvore de trabalho ainda será a mesma.git commit -a
derrota praticamente todos os aspectos do modelo de fluxo de trabalho / pensamento do git - toda mudança é comprometida. e se você quiser renomear o arquivo apenas, mas confirmar as alteraçõesindex.html
em outro commit?mobile.css
que eu deveria ter mencionado. Mas esse é o ponto da minha resposta: a página de manual diz issothe index is updated
quando você usagit-mv
. Obrigado pelostatus -a
esclarecimento, eu usei git 1.6.4git status
não estava detectando a renomeação. A execuçãogit commit -a --dry-run
após adicionar meus "novos" arquivos mostrou os renomeados e finalmente me deu confiança para confirmar!git status
Agora no git 1.9.1 se comporta comogit commit
.Você precisa adicionar os dois arquivos modificados ao índice antes que o git o reconheça como um movimento.
A única diferença entre
mv old new
egit mv old new
é que o git mv também adiciona os arquivos ao índice.mv old new
entãogit add -A
teria funcionado também.Note que você não pode simplesmente usar
git add .
porque isso não adiciona remoções ao índice.Consulte Diferença entre "git add -A" e "git add".
fonte
git add -A
link, muito útil, pois eu estava procurando por esse atalho!git add .
não adicionar remoções ao índice.O melhor é tentar você mesmo.
Agora, o git status e o git commit --dry-run -a mostram dois resultados diferentes, nos quais o status git mostra bbb.txt quando um novo arquivo / aaa.txt é excluído, e os comandos --dry-run mostram a renomeação real.
Agora vá em frente e faça o check-in.
Agora você pode ver que o arquivo é renomeado e o que é mostrado no status git está errado.
Moral da história: se você não tiver certeza se seu arquivo foi renomeado, emita um "git commit --dry-run -a". Se estiver mostrando que o arquivo foi renomeado, você estará pronto.
fonte
Para o git 1.7.x, os seguintes comandos funcionaram para mim:
Não havia necessidade do git add, pois o arquivo original (por exemplo, css / mobile.css) já estava nos arquivos confirmados anteriormente.
fonte
você precisa
git add css/mobile.css
do novo arquivo egit rm css/iphone.css
, portanto, o git sabe disso. então mostrará a mesma saída emgit status
você pode vê-lo claramente na saída de status (o novo nome do arquivo):
e (o nome antigo):
Eu acho que nos bastidores
git mv
nada mais é do que um script wrapper que faz exatamente isso: exclua o arquivo do índice e adicione-o com um nome diferentefonte
git rm css/iphone.css
porque achei que isso removeria a história existente. Talvez eu esteja entendendo mal o fluxo de trabalho no git.git rm
não removerá o histórico. Ele remove apenas uma entrada do índice para que o próximo commit não tenha a entrada. No entanto, ele ainda existirá nos commits ancestrais. O que você pode estar confuso é que (por exemplo)git log -- new
irá parar no ponto em que você se comprometeugit mv old new
. Se você deseja seguir os nomes renomeados, usegit log --follow -- new
.Vamos pensar nos seus arquivos da perspectiva do git.
Seu repositório possui (entre outros)
e está sob controle git:
Teste isso com:
Quando você faz
Da perspectiva do git,
Portanto, o git aconselha sobre arquivos que ele já conhece ( iphone.css ) e novos arquivos que ele detecta ( mobile.css ), mas somente quando os arquivos estão no índice ou no HEAD, o git começa a verificar seu conteúdo.
No momento, nem a "exclusão do iphone.css" nem o mobile.css estão no índice.
Adicione a exclusão do iphone.css ao índice
O git informa exatamente o que aconteceu: ( iphone.css é excluído. Nada mais aconteceu)
adicione o novo arquivo mobile.css
Desta vez, a exclusão e o novo arquivo estão no índice. Agora, o git detecta o contexto e o expõe como um renomeado. De fato, se os arquivos forem 50% semelhantes, ele detectará isso como uma renomeação, permitindo alterar mobile.css um pouco, mantendo a operação como uma renomeação.
Veja que isso é reproduzível em
git diff
. Agora que seus arquivos estão no índice, você deve usar--cached
. Edite mobile.css um pouco, adicione-o ao índice e veja a diferença entre:e
-M
é a opção "detectar renomeação" paragit diff
.-M
significa-M50%
(50% ou mais de semelhança fará o git expressá-lo como renomeado), mas você pode reduzi-lo para-M20%
(20%) se editar muito o mobile.css.fonte
Etapa 1: renomear o arquivo de oldfile para newfile
Etapa 2: git confirmar e adicionar comentários
Etapa 3: envie essa alteração para servidor remoto
fonte
git mv
, o novo arquivo já está no índice.Foi aí que você errou.
Somente após você adicionar o arquivo, o git o reconhecerá no conteúdo.
fonte
Você não encenou os resultados do seu movimento de busca. Acredito que se você fizesse a mudança via Finder e o fizesse
git add css/mobile.css ; git rm css/iphone.css
, o git calcularia o hash do novo arquivo e só então perceberia que os hashes dos arquivos correspondem (e, portanto, é uma renomeação).fonte
Nos casos em que você realmente precisa renomear os arquivos manualmente, por exemplo. usando um script para renomear em lote um monte de arquivos e, em seguida, usando
git add -A .
funcionou para mim.fonte
Para usuários do Xcode: Se você renomear seu arquivo no Xcode, verá o ícone do emblema mudar para acrescentar. Se você fizer uma confirmação usando o XCode, criará um novo arquivo e perderá o histórico.
Uma solução alternativa é fácil, mas você deve fazer isso antes de confirmar o uso do Xcode:
renomeado: Project / OldName.h -> Project / NewName.h renomeado: Project / OldName.m -> Project / NewName.m
Em seguida, volte ao XCode e você verá o distintivo alterado de A para M, e é possível salvar alterações adicionais ao usar o xcode agora.
fonte