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?
11 answers
Para git mv
a
Página de manual
diz:
Então, primeiro tens de actualizar o índice sozinho. (usandoO índice é actualizado após uma conclusão bem sucedida, [....]
git add mobile.css
). No entantogit 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
egit 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.
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.
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.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]}
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.
Foi aí que erraste.O Git irá reconhecer o ficheiro do conteúdo, em vez de o ver como um novo ficheiro não rastreado
É apenas Depois de adicionar o ficheiro, que o git irá reconhecê-lo a partir do conteúdo.
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
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.
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.
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:
- 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
- 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.