Como confirmar alterações de nome de arquivo com distinção entre maiúsculas e minúsculas no Git?

1302

Eu mudei um nome de alguns arquivos de-capitalizar a primeira letra, como em Name.jpga name.jpg. O Git não reconhece essas alterações e eu tive que excluir os arquivos e enviá-los novamente. Existe uma maneira de o Git fazer distinção entre maiúsculas e minúsculas ao verificar alterações nos nomes dos arquivos? Eu não fiz nenhuma alteração no próprio arquivo.

Gil Shulman
fonte
4
@ se isso não estiver correto, o Git realmente tem uma configuração que controla se ignora ou não a distinção entre maiúsculas e minúsculas.
6
Veja stackoverflow.com/a/24979063/6309 : desde o git 2.0.1, um simples git mvfunciona.
VonC 27/03
possível duplicata do Git: Alterar capitalização de nomes de arquivos
KyleMit
Consulte este post. Consegui confirmar, mas apenas usando o git commit -m "msg" sem nenhum caminho de arquivo como parâmetro. Atualizou o índice e fez check-in no arquivo. [Link] stackoverflow.com/questions/35790113/…
ARKS 5/16

Respostas:

1518

Você pode usar o git mv :

git mv -f OldFileNameCase newfilenamecase
Keith Smiley
fonte
12
isso me dá 'o diretório de origem está vazio', enquanto não está
WiseStrawberry
6
Usar o MacOS aqui (FS que não diferencia maiúsculas de minúsculas) e -f funcionou! Obrigado pela dica
caesarsol 15/12/16
49
Nas versões recentes, você não precisa mais do -fsinalizador.
Joshua Pinter
8
Não se esqueça de fornecer o caminho completo do arquivo. Óbvio, eu sei, mas me deixou por um tempo
rickrizzo
7
Para o topo votou comentário: você faz precisa do -finterruptor com a mais recente git (2,18) senão você poderá obter o fatal: destination existserro.
DeepSpace101
1038

Git tem uma configuração que diz que se deve ser sensível a maiúsculas ou minúsculas: core.ignorecase. Para dizer ao Git que faz distinção entre maiúsculas e minúsculas, basta definir esta configuração como false:

git config core.ignorecase false

Documentação

A partir da git configdocumentação :

core.ignorecase

Se true, essa opção permite várias soluções alternativas para permitir que o git funcione melhor em sistemas de arquivos que não diferenciam maiúsculas de minúsculas, como FAT. Por exemplo, se uma listagem de diretório descobrir makefilequando o git espera Makefile, o git assumirá que ele é realmente o mesmo arquivo e continuará lembrando-o como Makefile.

O padrão é falso, exceto que o git-clone (1) ou o git-init (1) analisará e definirá core.ignorecasetrue se apropriado quando o repositório for criado.

Sistemas de arquivos que não diferenciam maiúsculas de minúsculas

Os dois sistemas operacionais mais populares que possuem sistemas de arquivos que não diferenciam maiúsculas de minúsculas são

  • janelas
  • OS X

fonte
9
Em uma nota lateral, não acho que o próprio Mac OS X faça distinção entre maiúsculas e minúsculas. Em vez disso, é o sistema de arquivos que determina a distinção entre maiúsculas e minúsculas. Ao formatar uma partição HFS +, os usuários podem optar por torná-la sensível a maiúsculas ou minúsculas. A distinção entre maiúsculas e minúsculas é o padrão.
spaaarky21
225
Parece muito interessante notar nesta resposta que definir essa opção falseem um sistema de arquivos que não diferencia maiúsculas de minúsculas é uma má idéia . Isso não é necessariamente óbvio. Por exemplo, eu apenas tentei isso no meu Mac, pensando que isso resolveria meus problemas, depois renomeei um arquivo de productPageCtrl.jspara ProductPageCtrl.js. git statusviu um novo arquivo chamado, ProductPageCtrl.jsmas não achou que productPageCtrl.jstivesse sido excluído. Quando adicionei os novos arquivos, confirmei e enviei para o GitHub, o repositório do GitHub agora continha os dois arquivos, embora o meu (supostamente atualizado) repositório local tivesse apenas um.
Mark Amery
5
@ MarkAmery Isso parece muito com um bug no seu cliente Git. Você registrou um relatório?
Domi
24
@ Domi isso não é um bug, é um comportamento esperado. Na verdade, é uma má idéia definir isso como falso em um sistema de arquivos insensível, porque é isso que acontece. A razão pela qual o git não viu o arquivo em minúsculas foi excluído é que o sistema de arquivos não o relata como excluído, pois ignora o caso, enquanto o git não com esta opção definida como false. Não é que os nomes de arquivos não tenham letras maiúsculas ou minúsculas nos NTFS ou gordura, é apenas que a pesquisa de nome de arquivo está ignorando o caso.
ohcibi
15
@Domi git é inteligente o suficiente. É por isso que você não deve definir isso como false em um sistema de arquivos que não diferencia maiúsculas de minúsculas. Use git mvpara mover o arquivo e ver como o git o gerencia. Se você mover o arquivo sem o git, não há nada que o git possa fazer, pois o sistema de arquivos não está dizendo a verdade para o git. Este é um problema do ntfs / fat / hfs e thelike e não do git / linux.
precisa saber é
158

Usando o SourceTree, consegui fazer tudo isso a partir da interface do usuário

  1. Renomeie FILE.ext parawhatever.ext
  2. Preparar esse arquivo
  3. Agora renomeie whatever.ext parafile.ext
  4. Prepare esse arquivo novamente

É um pouco entediante, mas se você precisar fazer apenas alguns arquivos, é muito rápido

CBarr
fonte
5
O mesmo com o bash git
Alex78191
3
"Encenar esse arquivo" é a parte importante - nenhuma das outras respostas acima funcionou para mim. Na verdade, funcionou com o prompt de comando antigo e simples do Windows.
21717 Vlad Vladev
1
Não sabia que isso funcionava na área de preparação. Mas, no meu caso, eu queria modificar os nomes das pastas e alguns arquivos dentro dessas pastas. Então, renomeei todas as pastas para nomes temporários. Confirmou os novos nomes (todos os arquivos contidos) e os arquivos "excluídos". O Git sinalizou todos eles como "renomeados". Em seguida, renomeei todas essas pastas de volta para suas novas versões de caso e confirmadas novamente. Finalmente, mesclou esses 2 commits. Mas, com base no que você escreveu, eu poderia ter feito a coisa toda diretamente na área de satisfação, sem criar 2 confirmações + mesclagem.
ThermoX
3
Funciona também com gitkraken no nome da pasta.
Philippe Matray
Eu escrevi um script Python 3 para fazer esse trabalho tedioso: stackoverflow.com/a/58159822/4934640
usuário
126

Isto é o que eu fiz no OS X:

git mv File file.tmp
git mv file.tmp file

Duas etapas, porque, caso contrário, recebi o erro "arquivo existe". Talvez isso possa ser feito em uma etapa adicionando --cachedou algo assim.

Sijmen Mulder
fonte
21
como a resposta top sugere, -f(força) é a bandeira que você está procurando
rperryng
5
@perryng - não, a -fbandeira não ajuda caso o FS subjacente não faça distinção entre maiúsculas e minúsculas. No entanto, a solução de dois passos funcionou para mim
HEKTO
Usando um FS que não diferencia maiúsculas de minúsculas (no Mac) e -ffuncionou! Obrigado pela dica
caesarsol
Isso também funcionou com uma pasta no Windows sem a -fbandeira.
Nich
git -c "core.ignorecase=false" add .considerará os arquivos cujo caso foi alterado para confirmação.
Nietonfir 11/11
67

Às vezes, é útil alterar temporariamente a distinção entre maiúsculas e minúsculas do Git:

Método # 1 - Altere a distinção entre maiúsculas e minúsculas para um único comando:

git -c core.ignorecase=true checkout mybranchpara desativar a distinção entre maiúsculas e minúsculas para um único checkoutcomando. Ou, mais geralmente: . (Agradeço ao VonC por sugerir isso nos comentários.)git -c core.ignorecase= <<true or false>> <<command>>

Método # 2 - Altere a distinção entre maiúsculas e minúsculas para vários comandos:

Para alterar a configuração por mais tempo (por exemplo, se vários comandos precisarem ser executados antes de alterá-la novamente):

  1. git config core.ignorecase(isso retorna a configuração atual, por exemplo false).
  2. git config core.ignorecase <<true or false>> - defina a nova configuração desejada.
  3. ... Execute vários outros comandos ...
  4. git config core.ignorecase <<false or true>> - defina o valor de configuração de volta à sua configuração anterior.
Steve Chambers
fonte
1
Por que não diretamente git -c core.ignorecase=<true or false> checkout <<branch>>? Nada para redefinir depois.
VonC
2
Tive uma experiência estranha com o core.ignorecase proposto, trabalhando ao mudar de minúsculas para maiúsculas, mas não de maiúsculas para minúsculas. parece que a única solução confiável é parar de usar um sistema operacional que não reconhece o nome do arquivo.
aspiringGuru
Existe uma razão pela qual deve haver uma mudança temporária? Isso causaria algum problema se eu apenas deixasse as configurações alteradas para maiúsculas e minúsculas?
cytsunny
Isso pode depender de alguns fatores, principalmente se o sistema de arquivos de destino diferencia maiúsculas de minúsculas - consulte en.wikipedia.org/wiki/Case_sensitivity#In_filesystems . A alteração temporária pode ser necessária se o sistema de arquivos de implantação tiver distinção entre maiúsculas e minúsculas e o sistema de arquivos usado para desenvolvimento. Também no meu caso, trabalho em uma equipe em que todos devem ter as mesmas configurações do Git (isto é, diferencia maiúsculas de minúsculas); portanto, se eu desativá-lo, ele precisa ser temporário.
Steve Chambers
44

No OSX, para evitar esse problema e outros problemas no desenvolvimento de um sistema de arquivos que não diferenciam maiúsculas de minúsculas, você pode usar o Disk Utility para criar uma unidade / imagem de disco virtual que diferencia maiúsculas de minúsculas .

Execute o utilitário de disco, crie uma nova imagem de disco e use as seguintes configurações (ou altere conforme desejar, mas mantenha a distinção entre maiúsculas e minúsculas):

Captura de tela do Utilitário de disco do Mac

Certifique-se de informar ao git que agora está em um FS que diferencia maiúsculas de minúsculas:

git config core.ignorecase false
user1821510
fonte
15
Nah, a nuclear está executando uma unidade de inicialização totalmente diferencia maiúsculas de minúsculas no OSX. Você terá que viver sem aplicativos mal escritos (ahem, Adobe) ou executá-los em sua própria VM estúpida, mas vale a pena se você codificar principalmente para sistemas * nix.
Mike Marcacci
1
Esta é a única opção que funciona corretamente. Eu tentei o resto e você acaba em apuros, de um jeito ou de outro. Resolva o problema corretamente fazendo isso.
John Hunt
2
Observe que o Disk Utility possui um bug do OS X 10.11 - Ele não cria imagens com distinção entre maiúsculas e minúsculas. Você precisa usar a ferramenta de linha de comando hdiutil. apple.stackexchange.com/questions/217915/…
dellsala
7
Com o APFS em High Sierra, isso é ainda mais fácil. Clique no ícone de uma unidade com um sinal de adição e adicione um volume que diferencia maiúsculas de minúsculas sem limites de tamanho. Ele apenas compartilha espaço com o volume principal e monta em / Volumes / nome do volume.
Michael Fox
21

Tentei as seguintes soluções com outras respostas e elas não funcionaram:

Se o seu repositório estiver hospedado remotamente (GitHub, GitLab, BitBucket), você poderá renomear o arquivo na origem (GitHub.com) e forçar a renomeação do arquivo de maneira descendente.

As instruções abaixo pertencem ao GitHub, no entanto, a idéia geral por trás delas deve se aplicar a qualquer plataforma de hospedagem de repositório remoto. Lembre-se do tipo de arquivo que você está tentando renomear é importante, seja um tipo de arquivo que o GitHub considere editável (código, texto, etc.) ou não editável (imagem, binário, etc.) no navegador.

  1. Visite o GitHub.com
  2. Navegue para o seu repositório no GitHub.com e selecione a filial em que está trabalhando
  3. Usando a ferramenta de navegação de arquivos do site, navegue até o arquivo que você deseja renomear
  4. O GitHub permite editar o arquivo no navegador?
    • a.) Editável
      1. Clique no ícone "Editar este arquivo" (parece um lápis)
      2. Alterar o nome do arquivo na entrada de texto do nome do arquivo
    • b.) Não editável
      1. Abra o botão "Download" em uma nova guia e salve o arquivo no seu computador
      2. Renomeie o arquivo baixado
      3. Na guia anterior do GitHub.com, clique no ícone "Excluir este arquivo" (parece uma lixeira)
      4. Verifique se o branchnamebotão de opção "Confirmar diretamente na ramificação" está selecionado e clique no botão "Confirmar alterações"
      5. No mesmo diretório do GitHub.com, clique no botão "Upload de arquivos"
      6. Carregue o arquivo renomeado do seu computador
  5. Verifique se o branchnamebotão de opção "Confirmar diretamente na ramificação" está selecionado e clique no botão "Confirmar alterações"
  6. Localmente, faça checkout / busque / puxe o ramo
  7. Feito
gmeben
fonte
Renomeei diretamente no BitBucket e funcionou. Obrigado.
rsc
Bom saber. Essa técnica deveria, teoricamente, funcionar em qualquer plataforma de hospedagem de repositórios, mas eu estaria interessado em saber se existe alguma com a qual não funcionaria.
gmeben
Não funciona para arquivos que não podem ser editados no navegador, como imagens ou PDF; não há opção de edição, obviamente.
Abhijit Sarkar
@AbhijitSarkar Good point. Atualizei minha resposta para esses casos. Testei e verifiquei que estas instruções funcionam.
gmeben 11/01/19
Alguém consegue renomear um diretório dessa maneira?
Solvitieg 10/03
21

Semelhante à resposta de @ Sijmen, foi o que funcionou para mim no OSX ao renomear um diretório (inspirado nesta resposta de outro post):

git mv CSS CSS2
git mv CSS2 css

Simplesmente git mv CSS cssdeu o erro de argumento inválido: fatal: renaming '/static/CSS' failed: Invalid argumenttalvez porque o sistema de arquivos do OSX não diferencia maiúsculas de minúsculas

ps BTW, se você estiver usando o Django, o collectstatic também não reconheceria a diferença entre maiúsculas e minúsculas e você teria que fazer o acima, manualmente, também no diretório raiz estático

Anupam
fonte
19

1) renomeie o arquivo Name.jpgparaname1.jpg

2) confirmar arquivo removido Name.jpg

3) renomeie o arquivo name1.jpgparaname.jpg

4) emendar arquivo adicionado name.jpgao commit anterior

git add
git commit --amend
navalha
fonte
2
Estou recebendo isso fatal: bad source, source=name1.jpg, destination=name.jpgna etapa 3. Você tem alguma sugestão? Thx
Anthony Kong
1
Você não pode fazer um commit, apenas git add.
Alex78191 3/17/17
Parece muito hacky, não é? Ou remendo de macacos.
jeromej
18

Eu usei as seguintes etapas:

git rm -r --cached .
git add --all .
git commit -a -m "Versioning untracked files"
git push origin master

Para mim é uma solução simples

andrewvergel
fonte
Essa é a solução. E, diferentemente das outras respostas, funciona bem quando você está renomeando em lote. No glamourphilly.org, precisamos mudar todos os .Jpg para .jpg. No Finder você pode fazer renomeações em lote assim e esta resposta permite que você check-in.
William Entriken
11

Podemos usar o comando git mv. Exemplo abaixo, se renomearmos o arquivo abcDEF.js para abcdef.js, podemos executar o seguinte comando no terminal

git mv -f .\abcDEF.js  .\abcdef.js
Sandeep Shukla
fonte
8

O Mac OSX High Sierra 10.13 corrige isso um pouco. Basta criar uma partição APFS virtual para seus projetos git; por padrão, ela não tem limite de tamanho e não ocupa espaço.

  1. No Utilitário de Disco, clique no botão + enquanto o disco Container está selecionado
  2. Selecione APFS (diferencia maiúsculas de minúsculas) no formato
  3. Diga Sensitive
  4. Lucro
  5. Opcional: Crie uma pasta no Sensitive chamada giteln -s /Volumes/Sensitive/git /Users/johndoe/git

Sua unidade estará em /Volumes/Sensitive/

insira a descrição da imagem aqui

Como confirmar alterações de nome de arquivo com distinção entre maiúsculas e minúsculas no Git?

Ray Foss
fonte
Adoro essa sugestão: ela resolve o problema de maneira elegante e indolor, sem recorrer a soluções feias. Obrigado!
Phil Gleghorn
4

Já enfrentei esse problema várias vezes no MacOS. O Git diferencia maiúsculas de minúsculas, mas o Mac preserva apenas maiúsculas e minúsculas.

Alguém confirma um arquivo: Foobar.javae após alguns dias decide renomeá-lo para FooBar.java. Quando você pega o código mais recente, ele falha comThe following untracked working tree files would be overwritten by checkout...

A única maneira confiável que vi que corrige isso é:

  1. git rm Foobar.java
  2. Confirme com uma mensagem que você não pode perder git commit -m 'TEMP COMMIT!!'
  3. Puxar
  4. Isso abrirá um conflito forçando você a mesclar o conflito - porque sua alteração o excluiu, mas a outra alteração renomeou (daí o problema)
    1. Aceite sua alteração, que é a "exclusão"
    2. git rebase --continue
  5. Agora solte sua solução alternativa git rebase -i HEAD~2e dropasTEMP COMMIT!!
  6. Confirme se o arquivo agora é chamado FooBar.java
Ashwin Jayaprakash
fonte
3

Quando você renomeia muitos arquivos e alguns deles são apenas uma mudança de maiúsculas e minúsculas, é difícil lembrar qual é qual. "git moving" manualmente o arquivo pode ser bastante trabalhoso. Então, o que eu faria durante minhas tarefas de alteração de nome de arquivo é:

  1. remova todos os arquivos e pastas não-git para uma pasta / repositório diferente.
  2. confirmar a pasta git vazia atual (isso será exibido como todos os arquivos excluídos.)
  3. adicione todos os arquivos de volta à pasta / repositório git original.
  4. confirmar a pasta git não vazia atual.

Isso resolverá todos os problemas do caso sem tentar descobrir quais arquivos ou pastas você renomeou.

Ricardo Virtudazo Jr
fonte
Por que não git commmit --amendno parágrafo 4? Caso contrário, haverá uma confirmação extra com a remoção de todos os arquivos. Ou você pode usar git rebase -icom abóbora.
Alex78191 03/06/19
1

Se nada funcionou, use git rm filename para excluir o arquivo do disco e adicioná-lo novamente.

gopal Pandey
fonte
0

Tomei @CBarr resposta e escreveu um Script 3 Python para fazê-lo com uma lista de arquivos:

#!/usr/bin/env python3
# -*- coding: UTF-8 -*-

import os
import shlex
import subprocess

def run_command(absolute_path, command_name):
    print( "Running", command_name, absolute_path )

    command = shlex.split( command_name )
    command_line_interface = subprocess.Popen( 
          command, stdout=subprocess.PIPE, cwd=absolute_path )

    output = command_line_interface.communicate()[0]
    print( output )

    if command_line_interface.returncode != 0:
        raise RuntimeError( "A process exited with the error '%s'..." % ( 
              command_line_interface.returncode ) )

def main():
    FILENAMES_MAPPING = \
    [
        (r"F:\\SublimeText\\Data", r"README.MD", r"README.md"),
        (r"F:\\SublimeText\\Data\\Packages\\Alignment", r"readme.md", r"README.md"),
        (r"F:\\SublimeText\\Data\\Packages\\AmxxEditor", r"README.MD", r"README.md"),
    ]

    for absolute_path, oldname, newname in FILENAMES_MAPPING:
        run_command( absolute_path, "git mv '%s' '%s1'" % ( oldname, newname ) )
        run_command( absolute_path, "git add '%s1'" % ( newname ) )
        run_command( absolute_path, 
             "git commit -m 'Normalized the \'%s\' with case-sensitive name'" % (
              newname ) )

        run_command( absolute_path, "git mv '%s1' '%s'" % ( newname, newname ) )
        run_command( absolute_path, "git add '%s'" % ( newname ) )
        run_command( absolute_path, "git commit --amend --no-edit" )

if __name__ == "__main__":
    main()
do utilizador
fonte