git mv e alterar apenas caso de diretório

259

Enquanto encontrei uma pergunta semelhante , não encontrei uma resposta para o meu problema

Quando tento renomear o diretório de FOO para foo via git mv FOO fooeu recebo

fatal: renaming 'FOO' failed: Invalid argument

ESTÁ BEM. Então eu tentogit mv FOO foo2 && git mv foo2 foo

Mas quando eu tento confirmar via git commit .eu recebo

# On branch master
# Untracked files:
#   (use "git add <file>..." to include in what will be committed)
#
# foo
nothing added to commit but untracked files present (use "git add" to track)

Quando adiciono o diretório, git add foonada muda e git commit .me passa a mesma mensagem novamente.

O que estou fazendo de errado? Eu pensei que estava usando um sistema com distinção entre maiúsculas e minúsculas (OSX). Por que não posso simplesmente renomear o diretório?

oschrenk
fonte
10
O sistema de arquivos do OS X não diferencia maiúsculas de minúsculas.
Mipadi
2
@mipadi Ele pode operar no modo que diferencia maiúsculas de minúsculas, mas geralmente está desativado por padrão.
GordonM
1
Esta pergunta e suas respostas também são úteis no Windows. Considere desmarcar "osx"
Barett 21/01
1
Veja stackoverflow.com/a/24979063/6309 : desde o git 2.0.1, um simples git mvfunciona.
VonC 27/03
No Windows, você pode usar o regular git mv foo Foose usar um shell cygwin.
Andrew Scott

Respostas:

409

Você está em um ambiente que não diferencia maiúsculas de minúsculas. Além disso, adicionar com o -Anão cuidará do lado de remoção do mvGit como ele o entende. Aviso! Certifique-se de que não haja outras alterações ou arquivos não rastreados quando você fizer isso ou eles serão confirmados como parte dessa alteração! git stash -uprimeiro, faça isso e depois git stash popdepois. Continuando: Para contornar isso, faça o seguinte:

mv foo foo2
git add -A
git commit -m "renaming"
mv foo2 FOO
git add -A
git commit --amend -m "renamed foo to FOO"

Essa é a maneira mais extensa de alterar o diretório de trabalho, confirmar e depois recolher os 2 commits. Você pode simplesmente mover o arquivo no índice, mas para alguém novo no git, pode não ser explícito o suficiente sobre o que está acontecendo. A versão mais curta é

git mv foo foo2
git mv foo2 FOO
git commit -m "changed case of dir"

Conforme sugerido em um dos comentários, você também pode fazer uma nova análise interativa ( git rebase -i HEAD~5se o caso errado foi introduzido há 5 confirmações atrás) para corrigir o caso e não fazer com que o caso errado apareça em qualquer parte do histórico. Você deve ter cuidado se fizer isso, pois os hashes de consolidação a partir de então serão diferentes e outros terão que refazer ou mesclar novamente seu trabalho com esse passado recente da ramificação.

Isso está relacionado à correção do nome de um arquivo: O git não diferencia maiúsculas de minúsculas?

Adam Dymitruk
fonte
1
Obrigado. Isso estava me deixando louco. Eu não sabia sobre a opção -A ou --amend.
oschrenk
7
Cuidado com o -A, pois ele adiciona recursivamente todo o conteúdo do diretório atual, incluindo itens não rastreados. Pode ser melhor apenas git add foo2.
rich.e
2
Está correto. No entanto, você precisará realizar a remoção de foo2 e a adição de FOO separadamente. -Acuida de ambos. Vice-versa para o primeiro passo. Vou adicionar o aviso. Obrigado!
Adam Dymitruk 23/12/12
Você também pode limpar seu histórico com uma rebase interativa git rebase -i HEAD~2. Nota: Para simplificar isso, configure a mensagem final no seu primeiro commit e corrija o segundo.
Alex B.
5
Eu tive sucesso com git mv foo foo2; git mv foo2 FOO; git commit
Chris
146

Você deseja definir a opção core.ignorecasecomo false, o que fará com que o Git preste atenção aos casos em sistemas de arquivos que não a suportam nativamente. Para ativar em seu repo:

$ git config core.ignorecase false

Em seguida, você pode renomear o arquivo git mve ele funcionará conforme o esperado.

mipadi
fonte
1
Eu acho que isso pode ter efeitos indesejáveis ​​em outros lugares. Sistemas que não diferenciam maiúsculas de minúsculas devem deixar o Git pensar que é o mesmo diretório.
Adam Dymitruk
2
Eu adicionei a opção para a minha configuração global, mas isso não ajuda
oschrenk
3
Vejo algum comportamento estranho usando isso com o OSX. hum I modified a file that doesn't exist.. hum error: The following untracked working tree files would be overwritten by checkout:mas ... esses arquivos não existem.
Skylar Saveland
Era exatamente isso que eu estava procurando. Estou executando o CentOS 5.6 e ele não percebeu a mudança de caso.
precisa saber é o seguinte
5
Isso não funciona! No Git 1.8.3, o Git tratará o arquivo renomeado como um novo arquivo, em vez de removido + adicionado. Cometer isso deixará o repositório com dois arquivos iguais, por exemplo, foo e FOO existem! Mas quando check-out apenas um arquivo aparecer (mas um caso pode dominar o outro caso)
Johnny Wong
68

Consegui resolver isso usando o git 1.7.7 usando um nome de arquivo temporário:

$ git mv improper_Case improve_case2
$ git mv improve_case2 improve_case
$ git commit -m "<your message>"
mgadda
fonte
Interessante. Talvez o GIT tenha melhorado alguma coisa desde então. Quando eu topar com esse problema novamente, tentarei novamente.
Oschrenk
muito mais fácil fazê-lo desta maneira
olore
Trabalhou para mim no macOS.
Mr_Pouet
14

( git mv-variante livre.)

Eu encontrei esse problema no Git no Mac OS X 10.9. Eu resolvi da seguinte maneira:

git rm -r --cached /path/to/directory

Isso prepara o diretório para exclusão no Git, mas na verdade não remove nenhum arquivo físico ( --cached). Isso também faz com que o diretório, agora com o caso apropriado, seja exibido em arquivos não rastreados.

Então você pode fazer isso:

mv /path/to/directory /path/to/DIRECTORY
git add -A /path/to/DIRECTORY

O Git reconhecerá que você renomeou os arquivos e, quando o fizer, git statusdeverá ver várias renamed:linhas. Inspecione-os e verifique se eles parecem corretos e, se houver, você poderá confirmar as alterações normalmente.

wizonesolutions
fonte
Eu descobri que o mvcomando não funcionava para realmente renomear o diretório; Eu tive que renomeá-lo no Finder. Fora isso, essa correção funciona perfeitamente.
Adam S
9

Esta é uma solução rápida e segura de erros:

git mv -f path/to/foo/* path/to/FOO/

Aviso! Sempre renomeie todos os arquivos na pasta renomeada (use /*).

Não renomeie arquivos únicos. Isso leva a um erro, descrito nesta resposta .

Se você deseja ver primeiro o resultado, use -n:

git mv -f -n path/to/foo/* path/to/FOO/

Depois de fazer um mv:

  1. Confirmar alterações
  2. Checkout para qualquer outra revisão
  3. Saída de volta.

Agora o Git deveria ter renomeado a pasta AMBOS em seus arquivos internos e no sistema de arquivos.

Nick Volynkin
fonte
Isso é apenas para o Git 2.0.1, como mencionei nos comentários da pergunta acima? (referindo-se a stackoverflow.com/a/24979063/6309 )
VonC 11/11/2015
8

Force-o com a opção -f:

git mv -f FOO foo
konyak
fonte
Não funciona para mim. Minha configuração é "ignorecase = true" .git / config. A renomeação não pode ser preparada na área de preparação dessa maneira. (Git versão 1.8.3.msysgit.0) A solução de Adam Dymitruk é a única resposta certa.
Johnny Wong
@JohnnyWong mudar sua configuração para false, ele trabalhou para mim
Inder Kumar Rathore
Isso será atualizado nos computadores de todos os outros usuários se eles puxarem, mesmo que o computador esteja configurado para ignorar maiúsculas e minúsculas?
Bryce
@Bryce Não, você precisará confirmar as alterações e enviá-las ao repositório central antes que outros usuários possam fazer as alterações.
precisa saber é
3

Eu tive um problema relacionado.

Uma pasta chamada 'Pro' (criada primeiro) e outra 'pro' (criada por engano). No Mac, é a mesma coisa, mas diferente de acordo com o git.

$ git config core.ignorecase false

a configuração do git renomeia os arquivos para a pasta correta (obrigado) e também criou arquivos fantasmas em 'pro' (Não !!). Não pude adicionar alterações de arquivo fantasma à faixa e não pude fazer check-out de outros ramos, a menos que carregasse esses arquivos comigo, e também não consegui redefini-lo de alguma forma.

Em vez disso, eu fiz

$ git rm -r --cached pro
$ git status // => pro files removed, new Pro files untracked
$ git add Pro

Para torná-lo ainda mais seguro, eu o fiz em uma ramificação de correção separada e, em seguida, fui mesclada de volta à ramificação principal

Para a questão do arquivo fantasma criada por, qualquer guru pode explicar como e por quê? Desde já, obrigado.

Seeliang
fonte
2

Você não está usando um sistema de arquivos com distinção entre maiúsculas e minúsculas no OS X, a menos que você o escolha explicitamente. O HFS + pode fazer distinção entre maiúsculas e minúsculas, mas o padrão não diferencia maiúsculas de minúsculas.

Nicholas Knight
fonte
4
Usar o sistema de arquivos que diferencia maiúsculas de minúsculas no OS X não é uma boa ideia. Muitos aplicativos NÃO funcionam corretamente, aprendi ao tentar isso. Um problema específico é que o Adobe Photoshop se recusará a instalar, dizendo que o sistema de arquivos com distinção entre maiúsculas e minúsculas não é suportado.
Jspwain # 9/11
1

Aqui está uma solução realmente simples para todo o gitfoo nesta página.

  1. Copie os arquivos do seu projeto manualmente.
  2. git rm todos os arquivos.
  3. git commit como normal.
  4. adicione os arquivos manualmente.
  5. git adiciona todos os arquivos.
  6. git commit como normal.
  7. lucro.
Askdesigners
fonte
1
Isso funciona localmente, mas se alguém tentar, isso não mudará de caso.
Jason
Obrigado por isso ao me ajudar a corrigir as entradas duplas no git com casos diferentes. Eu usei uma variante disso. Apenas renomeei a pasta pai. Fiz um commit. Em seguida, renomeie a pasta pai novamente para o original. E fez um segundo commit. Agora as entradas antigas com o caso diferente desapareceram.
Dreamerkumar
0

Melhorando a resposta de Adam Dymitruk (bobo que o SO não me permita comentar sua resposta), o uso de "git mv" automaticamente encenará exatamente os arquivos movidos. Não é necessário esconderijo e o arriscado "git add -A" pode ser evitado:

old="abc";    new="ABC";
tmp="$old-renamed";
git mv "$old" "$tmp";
git commit -m "Renamed '$old' to '$tmp'.";
git mv "$tmp" "$new";
git commit --amend -m "Renamed '$old' to '$new'.";
Rainer Blome
fonte
0

Isso funcionou muito bem para mim no Windows. PowerShell usado com o seguinte:

  1. mv .\Folder-With-Wrong-Casing .\temp
  2. git add -A
  3. git commit -m "renamed folder with wrong casing to temp"
  4. mv .\temp .\Folder-with-Correct-Casing
  5. git add -A
  6. git commit --amend -m "Renamed to proper casing"
  7. (opcional) git push

Graças à resposta de Adam acima.

Tony
fonte