Lidar com a mudança de nomes dos ficheiros no git

eu teria lido que quando mudar o nome dos ficheiros no git , você deveria enviar quaisquer alterações, executar a sua mudança de nome e, em seguida, encenar o seu ficheiro renomeado. O Git irá reconhecer o arquivo a partir do conteúdo, ao invés de vê-lo como um novo arquivo não rastreado, e manter o histórico de mudanças.

No entanto, ao fazer isto esta noite, acabei por voltar a fazer isto.

> $ git status
# On branch master
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#   modified:   index.html
#

mudar o nome da minha 'stylesheet' no Localizador de iphone.css para mobile.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 pensa que apaguei um ficheiro CSS, e ... adicionei um novo. Não é o que eu quero, vamos desfazer o nome e deixar o git fazer o trabalho.

> $ git reset HEAD .
Unstaged changes after reset:
M   css/iphone.css
M   index.html
De volta ao ponto de partida.

> $ git status
# On branch master
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#   modified:   index.html
#

vamos usar git mv em vez disso.

> $ 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 porque é que o git não reconheceu o nome da primeira vez quando usei o Finder?

 392
Author: James Skemp, 2010-04-15

11 answers

Para git mv a Página de manual diz:

O índice é actualizado após uma conclusão bem sucedida, [....]

Então, primeiro tens de actualizar o índice sozinho. (usando git add mobile.css). No entanto
git status irá ainda mostrar dois ficheiros diferentes
$ git status
# On branch master
warning: LF will be replaced by CRLF in index.html
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#       modified:   index.html
#       new file:   mobile.css
#
# 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:    iphone.css
#

Você pode obter uma saída diferente executando git commit --dry-run -a o que resulta no que expect

Tanascius@H181 /d/temp/blo (master)
$ git commit --dry-run -a
# On branch master
warning: LF will be replaced by CRLF in index.html
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#       modified:   index.html
#       renamed:    iphone.css -> mobile.css
#
Não posso dizer-te exactamente porque vemos estas diferenças. entre git status e
git commit --dry-run -a, mas ... aqui é uma dica de Linus
O Git nem sequer se importa com o todo. "mudar o nome da detecção" internamente, e quaisquer commits que tenha feito com renomeações são totalmente independentes do heurística usamos então para mostrar os nomes.

A dry-run usa os mecanismos de renomeação reais, enquanto que a Provavelmente não.

 317
Author: tanascius, 2015-05-26 19:02:42

Tem de adicionar os dois ficheiros modificados ao índice antes que o git o reconheça como um movimento.

A única diferença entre mv old new e git mv old new é que o git mv também adiciona os ficheiros ao índice.

mv old new então git add -A também teria funcionado.

Lembre-se que não pode apenas usar git add . porque isso não adiciona remoções ao índice.

Ver diferença entre "git add-a" e " git add ."

 71
Author: nonrectangular, 2017-05-23 11:54:46
O melhor é tentar por si mesmo.
mkdir test
cd test
git init
touch aaa.txt
git add .
git commit -a -m "New file"
mv aaa.txt bbb.txt
git add .
git status
git commit --dry-run -a

Agora o estado do git e o git commit --dry-run-a mostra dois resultados diferentes onde o estado do git mostra o bbb.txt como um novo ficheiro/ aaa.o txt é apagado e os comandos --dry-run mostram o nome actual.

~/test$ git status

# On branch master
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#   new file:   bbb.txt
#
# 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)
#
#   deleted:    aaa.txt
#


/test$ git commit --dry-run -a

# On branch master
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#   renamed:    aaa.txt -> bbb.txt
#
Agora faça o check-in.
git commit -a -m "Rename"

Agora você pode ver que o arquivo é de fato renomeado, e o que é mostrado no estado do git está errado.

Moral da história: se não tem a certeza se o seu ficheiro foi renomeado, emite um "git commit --dry-run-a". Se estiver a mostrar que o ficheiro é renomeado, pode ir.
 17
Author: dimuthu, 2014-08-07 10:32:52

Você tem que git add css/mobile.css o novo arquivo e git rm css/iphone.css, então git sabe sobre isso. então ele vai mostrar a mesma saída em git status

Pode vê-lo claramente no resultado do Estado (o novo nome do ficheiro):

# Untracked files:
#   (use "git add <file>..." to include in what will be committed)

E (o nome antigo):

# Changed but not updated:
#   (use "git add/rm <file>..." to update what will be committed)

Eu acho que nos bastidores git mv não é nada mais do que um script de embalagem que faz exatamente isso: apagar o arquivo do índice e adicioná-lo sob um nome diferente {[[8]}

 9
Author: knittl, 2010-04-14 21:40:55
Vamos pensar nos seus ficheiros da perspectiva git.

Tenha em mente que o git não rastreia quaisquer meta-dados sobre os seus ficheiros

O vosso repositório tem (entre outros)

$ cd repo
$ ls
...
iphone.css
...

E está sob controlo git:

$ git ls-files --error-unmatch iphone.css &>/dev/null && echo file is tracked
file is tracked

Testa isto com:

$ touch newfile
$ git ls-files --error-unmatch newfile &>/dev/null && echo file is tracked
(no output, it is not tracked)
$ rm newfile

Quando o fizeres

$ mv iphone.css mobile.css

Do ponto de vista git,

  • Não há nenhum iphone.css (é suprimido-o git adverte sobre isso-).
  • Há um novo ficheiro. Móvel.css . Esses ficheiros não estão relacionados.

Então, o git aconselha sobre arquivos que já conhece ( iphone.css ) e novos ficheiros que detecta (móveis.css ) mas apenas quando os ficheiros estão no índice ou o GIT da cabeça começa a verificar o seu conteúdo.

Neste momento, nenhum iphone.supressão css " nor móvel.css estão no índice.

Adicione iphone.supressão do css no índice

$ git rm iphone.css
O Git diz-te exactamente o que aconteceu.: Iphone.css é suprimido. Não aconteceu mais nada.

Depois adicionar um novo ficheiro móvel.css

$ git add mobile.css

Desta vez tanto a remoção como o novo ficheiro estão no índice. Agora o git detecta que o contexto é o mesmo e expô-lo como um novo nome. Na verdade, se os arquivos são 50% semelhantes, ele irá detectar que como um nome de renomeação, que lhe permite mudar móvel.css um pouco enquanto mantém a operação como um novo nome.

Isto é reprodutível em git diff. Agora que seus arquivos estão no índice você deve usar --cached. Edit móvel.CSS um pouco, adicione isso ao índice e veja a diferença entre:

$ git diff --cached 

E

$ git diff --cached -M

-M é a opção "Detectar renomeações" para git diff. -M significa -M50% (50% ou mais similaridade fará com que o git o expresse como um novo nome), mas poderá reduzir isto para -M20% (20%) se editar o telemóvel.muito css.

 8
Author: albfan, 2015-05-09 20:53:28

O Git irá reconhecer o ficheiro do conteúdo, em vez de o ver como um novo ficheiro não rastreado

Foi aí que erraste.

É apenas Depois de adicionar o ficheiro, que o git irá reconhecê-lo a partir do conteúdo.

 7
Author: hasen, 2010-04-15 00:29:11

Passo 1: mudar o nome do ficheiro antigo para Ficheiro Novo

git mv #oldfile #newfile

Step2: git commit e adicionar comentários

git commit -m "rename oldfile to newfile"

Passo 3: Pressione esta mudança para um servidor remoto

git push origin #localbranch:#remotebranch
 7
Author: Haimei, 2014-05-29 17:33:10

Para o git 1, 7.x os seguintes comandos funcionaram para mim:

git mv css/iphone.css css/mobile.css
git commit -m 'Rename folder.' 

Não houve necessidade de adicionar git, uma vez que o arquivo original (ou seja, css/mobile.css) já estava nos arquivos comprometidos anteriormente.

 6
Author: GrigorisG, 2015-07-08 22:36:17
Não encenou os resultados do seu movimento de busca. Eu acredito que se você fez o movimento através de Finder e então fez {[[0]}, git iria calcular o hash do novo arquivo e só então perceber que os hashs dos arquivos correspondem (e, portanto, é um nome diferente).
 3
Author: MikeSep, 2010-04-14 21:37:13

Nos casos em que você realmente tem que mudar o nome dos arquivos manualmente, por exemplo. usar um script para mudar o nome de um monte de arquivos, em seguida, usando git add -A . funcionou para mim.

 2
Author: pckben, 2012-05-02 11:31:29

Para os utilizadores do Xcode: se o seu ficheiro mudar de nome no Xcode, verá o ícone do badge mudar para adicionar. Se você fizer um commit usando XCode, você realmente criará um novo arquivo e perderá o histórico.

Uma solução de trabalho é fácil, mas você tem que fazê-lo antes de se deslocar usando o Xcode:

  1. Faça um estado git na sua pasta. Você deve ver que as mudanças encenadas estão corretas:

Renomeado: Project / OldName.h - > Project / NewName.h renomeado: Project / OldName.m -> Project / NewName.m

  1. Faça commit-m 'name change'

Depois volte para o XCode e verá que o crachá mudou de A Para M e que é seguro Enviar alterações de furtur usando o xcode agora.

 1
Author: doozMen, 2012-08-17 07:47:27