É possível mover / renomear arquivos no Git e manter seu histórico?

667

Gostaria de renomear / mover uma subárvore do projeto no Git, movendo-a de

/project/xyz

para

/components/xyz

Se eu usar um plain git mv project components, todo o histórico de commit dos xyz projectse perderá. Existe uma maneira de mudar isso de modo que a história seja mantida?

sgargan
fonte
2
Eu só quero observar que acabei de testar os arquivos em movimento via sistema de arquivos e, após confirmar (via intellij), posso ver o histórico inteiro (incluindo o histórico quando estava em um local diferente) ao visualizar o histórico (novamente no intellij). Estou assumindo que a intellij não está fazendo nada de especial para fazer isso, então é bom saber que pelo menos a história pode ser rastreada.
BT
Para as regras seguidas pelo Git ao detectar uma renomeação de diretório, veja minha resposta abaixo
VonC:
Eu escrevi uma resposta aqui. Eu espero que dê certo. stackoverflow.com/questions/10828267/…
Mahmut EFE

Respostas:

651

O Git detecta renomeação em vez de persistir na operação com a confirmação, portanto, use git mvou mvnão importa.

O logcomando usa um --followargumento que continua o histórico antes de uma operação de renomeação, ou seja, procura por conteúdo semelhante usando as heurísticas:

http://git-scm.com/docs/git-log

Para pesquisar o histórico completo, use o seguinte comando:

git log --follow ./path/to/file
Troels Thomsen
fonte
63
Eu suspeito que isso é uma consideração de desempenho. Se você não precisar do histórico completo, levará mais tempo para digitalizar o conteúdo. A maneira mais fácil é configurar um alias git config alias.logf "log --follow"e apenas escrever git logf ./path/to/file.
Troels Thomsen
13
@TroelsThomsen este e-mail por Linus Torvalds, ligado a partir de esta resposta , indica que é uma escolha de design intencional de Git já que é supostamente muito mais poderoso do rastreamento renomeações etc.
Emil Lundberg
127
Esta resposta é um pouco enganadora. O Git "detecta renomeação", mas muito tarde no jogo; a questão é perguntar como você garante que o Git rastreie os renomeados, e alguém lendo isso pode facilmente inferir que o Git os detecta automaticamente para você e toma nota disso. Isso não. O Git não tem tratamento real de renomeação e, em vez disso, existem ferramentas de mesclagem / log que tentam descobrir o que aconteceu - e raramente acertam. Linus tem um argumento equivocado, mas veemente, de por que o git nunca deve fazê-lo da maneira certa e rastrear renomeados explicitamente. Então, nós estamos presos aqui.
Chris Moschini
29
Importante: se você renomear um diretório, por exemplo, durante a renomeação de um pacote Java, execute duas confirmações, primeiro para o comando 'git mv {old} {new}', depois para as atualizações de todos os arquivos Java que referenciam o diretório de pacote alterado. Caso contrário, o git não poderá rastrear os arquivos individuais, mesmo com o parâmetro --follow.
Nn4l
44
Embora Linus provavelmente cometa muito poucos erros, isso parece ser um. Simplesmente renomear uma pasta faz com que um delta maciço seja carregado no GitHub. O que me deixa cauteloso em renomear minhas pastas ... mas isso é uma grande camisa-de-força para um programador. Ocasionalmente, TENHO DE redefinir o significado de algo ou alterar a forma como as coisas são categorizadas. Linus: "Em outras palavras, eu estou certo. Estou sempre certo, mas às vezes estou mais certo do que em outros momentos. E, caramba, quando digo 'arquivos não importam', estou realmente certo ( tm). " ... Eu tenho minhas dúvidas sobre isso.
Gabe Halsmer 11/09/2015
94

É possível renomear um arquivo e manter o histórico intacto, embora isso faça com que o arquivo seja renomeado em todo o histórico do repositório. Provavelmente, isso é apenas para os amantes obsessivos do git-log e tem algumas implicações sérias, incluindo estas:

  • Você pode reescrever um histórico compartilhado, que é o mais importante NÃO durante o uso do Git. Se alguém clonou o repositório, você o interromperá. Eles terão que re-clonar para evitar dores de cabeça. Isso pode ser bom se a renomeação for importante o suficiente, mas você precisará considerar isso com cuidado - pode acabar perturbando toda uma comunidade de código-fonte aberto!
  • Se você referenciou o arquivo usando seu nome antigo anteriormente no histórico do repositório, está efetivamente quebrando versões anteriores. Para remediar isso, você terá que fazer um pouco mais de pular de arco. Não é impossível, apenas tedioso e possivelmente não vale a pena.

Agora, como você ainda está comigo, provavelmente é um desenvolvedor solo que renomeia um arquivo completamente isolado. Vamos mover um arquivo usando filter-tree!

Suponha que você vá mover um arquivo oldpara uma pasta dire dê o nomenew

Isso poderia ser feito git mv old dir/new && git add -u dir/new, mas isso quebra a história.

Em vez de:

git filter-branch --tree-filter 'if [ -f old ]; then mkdir dir && mv old dir/new; fi' HEAD

irá refazer cada commit no branch, executando o comando nos ticks para cada iteração. Muitas coisas podem dar errado quando você faz isso. Normalmente, testo para ver se o arquivo está presente (caso contrário, ainda não está lá para ser movido) e, em seguida, execute as etapas necessárias para calçar a árvore da maneira que eu preferir. Aqui você pode acessar os arquivos para alterar as referências ao arquivo e assim por diante. Bata-se para fora! :)

Quando concluído, o arquivo é movido e o log está intacto. Você se sente como um pirata ninja.

Além disso; O diretório mkdir é necessário apenas se você mover o arquivo para uma nova pasta, é claro. O if evitará a criação desta pasta mais cedo no histórico do que o seu arquivo existe.

Øystein Steimler
fonte
57
Como um obsessivo amante do git-log, eu não aceitaria isso. Os arquivos não foram nomeados assim, nesses momentos, portanto, a história reflete uma situação inexistente. Quem sabe que testes podem quebrar no passado! O risco de quebrar versões anteriores praticamente não vale a pena.
Vincent Vincent
7
@Incent Você está absolutamente certo e tentei ser o mais claro possível sobre a improbabilidade dessa solução ser apropriada. Também acho que estamos falando de dois significados da palavra "história", neste caso, aprecio os dois.
Øystein Steimler
6
Acho que há situações em que alguém pode precisar disso. Digamos que desenvolvi algo em meu ramo pessoal, que agora quero mesclar a montante. Mas eu descubro que o nome do arquivo não é apropriado, então eu o altero para todo o meu ramo pessoal. Dessa forma, posso manter uma história limpa e adequada e ter o nome correto desde o início.
user2291758
3
@ user2291758 esse é o meu caso de uso. Esses comandos git mais poderosos são perigosos, mas isso não significa que eles não tenham casos de uso muito convincentes, se você souber o que está fazendo!
philix 01/09/16
1
se possível, o uso do --index-filterfor rename será muito mais rápido, pois a árvore não precisará ser registrada e retornada a cada commit. --index-filteratua diretamente em cada índice de confirmação.
Thomas Guyot-Sionnest
87

Não.

A resposta curta é NÃO . Não é possível renomear um arquivo no Git e lembrar o histórico. E é uma dor.

Há rumores de que git log --follow--find-copies-harderfuncionará, mas não funciona para mim, mesmo se houver zero alterações no conteúdo do arquivo e as alterações tiverem sido feitas git mv.

(Inicialmente eu usei Eclipse para renomear e pacotes de atualização em uma única operação, o que pode ter confundido Git. Mas isso é uma coisa muito comum de fazer. --followParece funcionar se apenas uma mvé realizada e, em seguida, um commite mvnão é muito longe.)

Linus diz que você deve entender todo o conteúdo de um projeto de software de forma holística, sem precisar rastrear arquivos individuais. Infelizmente, meu cérebro pequeno não pode fazer isso.

É realmente irritante que tantas pessoas tenham repetido sem pensar a afirmação de que o Git rastreia automaticamente os movimentos. Eles perderam meu tempo. Git não faz isso. Por design (!) O Git não controla movimentos.

Minha solução é renomear os arquivos de volta aos seus locais originais. Mude o software para caber no controle de origem. Com o Git, você parece ter que "acertar" da primeira vez.

Infelizmente, isso interrompe o Eclipse, que parece usar --follow. git log --followàs vezes não mostra o histórico completo de arquivos com históricos de renomeação complicados, mesmo que o git logfaça. (Eu não sei porque.)

(Existem alguns hacks muito inteligentes que retrocedem e reeditam trabalhos antigos, mas são bastante assustadores. Consulte GitHub-Gist: emiller / git-mv-with-history .)

Tuntable
fonte
2
Eu acredito que você está correto. Eu estava apenas tentando usar o php-cs-fixer para reformatar a fonte do meu projeto Laravel 5, mas ele insiste em alterar a capitalização das cláusulas do espaço para nome para corresponder ao valor em minúscula da pasta do aplicativo. Mas os namespaces (ou carregamentos automáticos do compositor) funcionam apenas com o CamelCase. Preciso alterar a capitalização da pasta para App, mas isso faz com que minhas alterações sejam perdidas. Este é o exemplo mais trivial, mas mostra como a heurística do git não é capaz de seguir nem mesmo as mais simples alterações de nome (--follow e --find-copy-hard mais devem ser a regra, não a exceção).
Zack Morris
6
git -1, subversão +1
Cosmin
Isso ainda é verdade? Essa é mais uma razão para eu ficar com o tfs por enquanto, manter o histórico de um arquivo movido / renomeado é essencial em um projeto grande.
Cesar
@ Cesar Se por "lembrar a história", ele quer dizer "siga renomeados ao visualizar o log" (que é a única coisa útil com a qual devemos nos preocupar), isso nunca foi verdade! O Git não "grava" renomeação, mas as ferramentas podem detectá-las facilmente e nos apresentar renomeações e movimentos. Se "não funcionar" para alguém, ele / ela deve alterar as ferramentas que está usando. Existem muitas GUIs maravilhosas do Git que têm essa capacidade.
Mohammad Dehghan
A resposta curta é sim. A versão atual do Git também suporta "git log --follow". e eu concordo com @MohammadDehghan
inserida em
43
git log --follow [file]

mostrará a história através de renomeações.

Erik Hesselink
fonte
29
Parece que isso exige que você confirme apenas a renomeação antes de começar a modificar o arquivo. Se você mover o arquivo (no shell) e depois alterá-lo, todas as apostas serão desativadas.
yoyo
22
@ yoyo: isso ocorre porque o git não rastreia renomeados, ele os detecta. A git mvbasicamente faz a git rm && git add. Existem opções como -M90/ --find-renames=90considerar um arquivo a ser renomeado quando ele é 90% idêntico.
vdboor
22

Eu faço:

git mv {old} {new}
git add -u {new}
James M. Greene
fonte
3
O -u não parece fazer nada por mim, é suposto atualizar o histórico?
Jeremy
1
Talvez você queira o comportamento de -Avez? Novamente, veja aqui: git-scm.com/docs/git-add
James M. Greene
1
Ele adiciona os arquivos, no entanto, não atualiza o histórico, para que 'git log file name' mostre o histórico completo. Ele mostra apenas o histórico completo se você ainda usar a opção --follow.
Jeremy
3
Fiz um refator complicado que moveu um diretório de inclusão (usando mv, não git mv) e depois alterei muitos caminhos #include nos arquivos renomeados. O git não conseguiu encontrar semelhança suficiente para acompanhar a história. Mas git add -u era exatamente o que eu precisava. O status git agora indica "renomeado", onde antes mostrava "excluído" e "novo arquivo".
AndyJost
1
Existem muitas perguntas sobre SO que abordam o objetivo de git add -u. Os documentos do Git tendem a ser inúteis e são o último lugar que eu gostaria de procurar. Aqui está um post mostrando git add -uem ação: stackoverflow.com/a/2117202 .
Nobar
17

Gostaria de renomear / mover uma subárvore do projeto no Git, movendo-a de

/project/xyz

para

/ components / xyz

Se eu usar um plain git mv project components, todo o histórico de consolidação do xyzprojeto será perdido.

Não (oito anos depois, Git 2.19, terceiro trimestre de 2018), porque o Git detectará a renomeação do diretório , e isso agora está melhor documentado.

Consulte commit b00bf1c , commit 1634688 , commit 0661e49 , commit 4d34dff , commit 983f464 , commit c840e1a , commit 9929430 (27 jun 2018) e commit d4e8062 , commit 5dacd4a (25 jun 2018) por Elijah Newren ( newren) .
(Incorporado por Junio ​​C Hamano - gitster- in commit 0ce5a69 , 24 de jul de 2018)

Isso agora é explicado em Documentation/technical/directory-rename-detection.txt:

Exemplo:

Quando todos x/a, x/be x/cforam movidos para z/a, z/be z/c, é provável que o x/dacréscimo nesse meio tempo também deseje passar z/d, levando a dica de que o diretório inteiro ' x' mudou para ' z'.

Mas são muitos outros casos, como:

um lado do histórico renomeia x -> ze o outro renomeia algum arquivo para x/e, fazendo com que a mesclagem faça uma renomeação transitiva.

Para simplificar a detecção de renomeação de diretório, essas regras são aplicadas pelo Git:

algumas regras básicas limitam quando a detecção de renomeação de diretório se aplica:

  1. Se um determinado diretório ainda existir nos dois lados de uma mesclagem, não consideramos que ele tenha sido renomeado.
  2. Se um subconjunto de arquivos a serem renomeados tiverem um arquivo ou diretório no caminho (ou estariam no caminho um do outro), "desative" o nome do diretório para esses subcaminhos específicos e relate o conflito ao usuário .
  3. Se o outro lado do histórico renomeou um diretório para um caminho que seu lado do histórico renomeou, ignore essa renomeação específica do outro lado do histórico para qualquer renomeação implícita de diretório (mas avise o usuário).

Você pode ver muitos testes t/t6043-merge-rename-directories.sh, que também apontam que:

  • a) Se as renomeações dividem um diretório em dois ou mais, o diretório com mais renomeações "vence".
  • b) Evite a detecção de renomeação de diretório para um caminho, se esse caminho for a fonte de uma renomeação nos dois lados de uma mesclagem.
  • c) Aplique somente renomeamentos implícitos de diretório a diretórios se o outro lado do histórico for o responsável pela renomeação.
VonC
fonte
15

Objetivo

  • Use (inspirado na Smar , emprestado da Exherbo )git am
  • Adicionar histórico de confirmação de arquivos copiados / movidos
  • De um diretório para outro
  • Ou de um repositório para outro

Limitação

  • Tags e ramificações não são mantidas
  • O histórico é cortado na renomeação do arquivo de caminho (renomeação do diretório)

Sumário

  1. Extrair histórico no formato de email usando
    git log --pretty=email -p --reverse --full-index --binary
  2. Reorganizar a árvore de arquivos e atualizar nomes de arquivos
  3. Anexar novo histórico usando
    cat extracted-history | git am --committer-date-is-author-date

1. Extrair histórico no formato de email

Exemplo: história Extrato de file3, file4efile5

my_repo
├── dirA
│   ├── file1
│   └── file2
├── dirB            ^
│   ├── subdir      | To be moved
│   │   ├── file3   | with history
│   │   └── file4   | 
│   └── file5       v
└── dirC
    ├── file6
    └── file7

Definir / limpar o destino

export historydir=/tmp/mail/dir       # Absolute path
rm -rf "$historydir"    # Caution when cleaning the folder

Extrair histórico de cada arquivo no formato de email

cd my_repo/dirB
find -name .git -prune -o -type d -o -exec bash -c 'mkdir -p "$historydir/${0%/*}" && git log --pretty=email -p --stat --reverse --full-index --binary -- "$0" > "$historydir/$0"' {} ';'

Infelizmente opção --followou --find-copies-hardernão pode ser combinada com --reverse. É por isso que o histórico é cortado quando o arquivo é renomeado (ou quando um diretório pai é renomeado).

Histórico temporário em formato de email:

/tmp/mail/dir
    ├── subdir
    │   ├── file3
    │   └── file4
    └── file5

Dan Bonachea sugere inverter os loops do comando git log generation nesta primeira etapa: em vez de executar o git log uma vez por arquivo, execute-o exatamente uma vez com uma lista de arquivos na linha de comando e gere um único log unificado. Dessa maneira, as confirmações que modificam vários arquivos permanecem como uma única confirmação no resultado e todas as novas confirmações mantêm sua ordem relativa original. Observe que isso também requer alterações na segunda etapa abaixo ao reescrever nomes de arquivos no log (agora unificado).


2. Reorganize a árvore de arquivos e atualize os nomes de arquivos

Suponha que você queira mover esses três arquivos neste outro repositório (pode ser o mesmo repositório).

my_other_repo
├── dirF
│   ├── file55
│   └── file56
├── dirB              # New tree
│   ├── dirB1         # from subdir
│   │   ├── file33    # from file3
│   │   └── file44    # from file4
│   └── dirB2         # new dir
│        └── file5    # from file5
└── dirH
    └── file77

Portanto, reorganize seus arquivos:

cd /tmp/mail/dir
mkdir -p dirB/dirB1
mv subdir/file3 dirB/dirB1/file33
mv subdir/file4 dirB/dirB1/file44
mkdir -p dirB/dirB2
mv file5 dirB/dirB2

Seu histórico temporário é agora:

/tmp/mail/dir
    └── dirB
        ├── dirB1
        │   ├── file33
        │   └── file44
        └── dirB2
             └── file5

Altere também nomes de arquivos no histórico:

cd "$historydir"
find * -type f -exec bash -c 'sed "/^diff --git a\|^--- a\|^+++ b/s:\( [ab]\)/[^ ]*:\1/$0:g" -i "$0"' {} ';'

3. Aplique novo histórico

Seu outro repo é:

my_other_repo
├── dirF
│   ├── file55
│   └── file56
└── dirH
    └── file77

Aplicar confirmações de arquivos de histórico temporários:

cd my_other_repo
find "$historydir" -type f -exec cat {} + | git am --committer-date-is-author-date

--committer-date-is-author-datepreserva os carimbos de data e hora de confirmação originais (comentário de Dan Bonachea ).

Seu outro repo é agora:

my_other_repo
├── dirF
│   ├── file55
│   └── file56
├── dirB
│   ├── dirB1
│   │   ├── file33
│   │   └── file44
│   └── dirB2
│        └── file5
└── dirH
    └── file77

Use git statuspara ver a quantidade de confirmações prontas para serem enviadas :-)


Truque extra: verifique arquivos renomeados / movidos em seu repositório

Para listar os arquivos que foram renomeados:

find -name .git -prune -o -exec git log --pretty=tformat:'' --numstat --follow {} ';' | grep '=>'

Mais personalizações: você pode concluir o comando git logusando as opções --find-copies-harderou --reverse. Você também pode remover as duas primeiras colunas usando cut -f3-e cumprimentando o padrão completo '{. * =>. *}'.

find -name .git -prune -o -exec git log --pretty=tformat:'' --numstat --follow --find-copies-harder --reverse {} ';' | cut -f3- | grep '{.* => .*}'
olibre
fonte
4
CUIDADO: Essa técnica divide confirmações que alteram 2 ou mais arquivos em confirmações fragmentadas separadas e, além disso, embaralha sua ordem classificando no nome do arquivo (para que os fragmentos de uma confirmação original não apareçam adjacentes no histórico linear). O histórico resultante é, portanto, apenas "correto" em uma base de arquivo por arquivo. Se você estiver movendo mais de um arquivo, NENHUMA das novas confirmações no histórico resultante representará uma captura instantânea consistente dos arquivos movidos que já existiram no histórico do repositório original.
Dan Bonachea 15/11
2
Olá @DanBonachea. Obrigado pelo seu feedback interessante. Migrei com êxito alguns repositórios contendo vários arquivos usando essa técnica (mesmo com arquivos renomeados e arquivos movidos entre diretórios). O que você sugere para mudar nesta resposta. Você acha que devemos adicionar um banner WARNING na parte superior desta resposta, explicando as limitações dessa técnica? Cheers
olibre
2
Eu adaptei essa técnica para evitar o problema, invertendo os loops do comando git log generation na etapa 1. Ou seja. em vez de executar o git log uma vez por arquivo, execute-o exatamente uma vez com uma lista de arquivos na linha de comando e gere um único log unificado. Dessa maneira, confirmações que modificam 2 ou mais arquivos permanecem como uma única confirmação no resultado e todas as novas confirmações mantêm sua ordem relativa original. Observe que isso também requer alterações na etapa 2 ao reescrever nomes de arquivos no log (agora unificado). Também usei git am --committer-date-is-author-date para preservar os carimbos de data e hora originais de confirmação.
precisa saber é o seguinte
1
Obrigado por sua experimentação e compartilhamento. Atualizei um pouco a resposta para outros leitores. No entanto, levei um tempo para testar seu processamento. Sinta-se à vontade para editar esta resposta se desejar fornecer exemplos de linhas de comando. Cheers;)
olibre
4

Eu segui esse processo de várias etapas para mover o código para o diretório pai e reter o histórico.

Etapa 0: criou um ramo 'histórico' a partir de 'mestre' para guarda

Etapa 1: use a ferramenta git-filter-repo para reescrever o histórico. Este comando abaixo moveu a pasta 'FolderwithContentOfInterest' para um nível acima e modificou o histórico de confirmação relevante

git filter-repo --path-rename ParentFolder/FolderwithContentOfInterest/:FolderwithContentOfInterest/ --force

Etapa 2: nesse momento, o repositório GitHub perdeu o caminho do repositório remoto. Referência remota adicionada

git remote add origin [email protected]:MyCompany/MyRepo.git

Etapa 3: extrair informações no repositório

git pull

Etapa 4: conectar a ramificação perdida local à ramificação de origem

git branch --set-upstream-to=origin/history history

Etapa 5: conflito de mesclagem de endereços para a estrutura de pastas, se solicitado

Etapa 6: Empurre !!

git push

Nota: O histórico modificado e a pasta movida parecem já estar confirmados. enter code here

Feito. O código é movido para o diretório pai / desejado, mantendo o histórico intacto!

Parag Bangad
fonte
2

Embora o núcleo do Git, o encanamento do Git não registre as renomeações, o histórico que você exibe com o log de porcelana "Git" pode detectá-las, se quiser.

Para um determinado git loguso, a opção -M:

git log -p -M

Com uma versão atual do Git.

Isso funciona para outros comandos como git diff também.

Existem opções para tornar as comparações mais ou menos rigorosas. Se você renomear um arquivo sem fazer alterações significativas no arquivo ao mesmo tempo, será mais fácil para o log e os amigos do Git detectar a renomeação. Por esse motivo, algumas pessoas renomeiam arquivos em um commit e os alteram em outro.

Há um custo no uso da CPU sempre que você pede ao Git para descobrir onde os arquivos foram renomeados; portanto, você deve usá-lo ou não, e quando, depende de você.

Se você deseja sempre ter seu histórico relatado com detecção de renomeação em um repositório específico, você pode usar:

git config diff.renames 1

Arquivos movendo-se de um diretório para outro são detectados. Aqui está um exemplo:

commit c3ee8dfb01e357eba1ab18003be1490a46325992
Author: John S. Gruber <[email protected]>
Date:   Wed Feb 22 22:20:19 2017 -0500

    test rename again

diff --git a/yyy/power.py b/zzz/power.py
similarity index 100%
rename from yyy/power.py
rename to zzz/power.py

commit ae181377154eca800832087500c258a20c95d1c3
Author: John S. Gruber <[email protected]>
Date:   Wed Feb 22 22:19:17 2017 -0500

    rename test

diff --git a/power.py b/yyy/power.py
similarity index 100%
rename from power.py
rename to yyy/power.py

Observe que isso funciona sempre que você estiver usando diff, não apenas com git log. Por exemplo:

$ git diff HEAD c3ee8df
diff --git a/power.py b/zzz/power.py
similarity index 100%
rename from power.py
rename to zzz/power.py

Como avaliação, fiz uma pequena alteração em um arquivo em um ramo de recurso e o confirmei e, no ramo mestre, renomei o arquivo, confirmei e, em seguida, fiz uma pequena alteração em outra parte do arquivo e o confirmei. Quando fui para o recurso branch e mesclado a partir do master, a mesclagem renomeou o arquivo e mesclou as alterações. Aqui está a saída da mesclagem:

 $ git merge -v master
 Auto-merging single
 Merge made by the 'recursive' strategy.
  one => single | 4 ++++
  1 file changed, 4 insertions(+)
  rename one => single (67%)

O resultado foi um diretório de trabalho com o arquivo renomeado e as duas alterações de texto feitas. Portanto, é possível que o Git faça a coisa certa, apesar de não rastrear explicitamente os renomeados.

Esta é uma resposta tardia a uma pergunta antiga, portanto as outras respostas podem estar corretas para a versão Git na época.

John S Gruber
fonte
1

Primeiro, crie uma confirmação independente com apenas uma renomeação.

Em seguida, quaisquer alterações eventuais no conteúdo do arquivo serão colocadas na confirmação separada.

Jakub Pawlowski
fonte
1

Para renomear um diretório ou arquivo (não sei muito sobre casos complexos, pode haver algumas ressalvas):

git filter-repo --path-rename OLD_NAME:NEW_NAME

Para renomear um diretório nos arquivos que o mencionam (é possível usar retornos de chamada, mas não sei como):

git filter-repo --replace-text expressions.txt

expressions.txté um arquivo preenchido com linhas como literal:OLD_NAME==>NEW_NAME(é possível usar o RE do Python com regex:ou glob comglob: ).

Para renomear um diretório em mensagens de confirmações:

git-filter-repo --message-callback 'return message.replace(b"OLD_NAME", b"NEW_NAME")'

As expressões regulares do Python também são suportadas, mas devem ser escritas em Python manualmente.

Se o repositório for original, sem controle remoto, você precisará adicionar --force para forçar uma reescrita. (Você pode criar um backup do seu repositório antes de fazer isso.)

Se você não deseja preservar as referências (elas serão exibidas no histórico de ramificações da Git GUI), será necessário adicionar --replace-refs delete-no-add.

Pugsley
fonte
0

Simplesmente mova o arquivo e prepare-o com:

git add .

Antes de confirmar, você pode verificar o status:

git status

Isso mostrará:

Changes to be committed:
  (use "git restore --staged <file>..." to unstage)
        renamed:    old-folder/file.txt -> new-folder/file.txt

Eu testei com o Git versão 2.26.1.

Extraído da página de ajuda do GitHub .

Júnior
fonte
-3

Eu faço mover os arquivos e depois faço

git add -A

que coloca na área de saturação todos os arquivos excluídos / novos. Aqui o git percebe que o arquivo foi movido.

git commit -m "my message"
git push

Não sei por que, mas isso funciona para mim.

Xelian
fonte
O truque aqui é que você não precisa alterar uma única letra, mesmo que você altere algo e pressione Ctrl + Z, o histórico será quebrado. Portanto, nesse caso, se você escrever algo, reverta o arquivo e mova-o novamente e faça um único add-> confirmar.
Xelian