O Git 2.18 (Q2 2018) melhorará consideravelmente a --preserve-mergeopção adicionando uma nova opção.
" git rebase" aprendi " --rebase-merges" a transplantar toda a topologia do gráfico de confirmação em outro lugar .
(Observação: o Git 2.22, segundo trimestre de 2019, na verdade é preterido --preserve-merge , e o Git 2.25, primeiro trimestre de 2020, para de anunciar o resultado " git rebase --help" )
Veja cometer 25cff9f , cometer 7543f6f , cometer 1131ec9 , cometer 7ccdf65 , cometer 537e7d6 , cometer a9be29c , cometer 8f6aed7 , cometer 1644c73 , cometer d1e8b01 , cometer 4c68e7d , cometer 9055e40 , cometer cb5206e , cometer a01c2a5 , cometer 2f6b1d1 , cometer bf5c057 (25 de abril de 2018) de Johannes Schindelin ( dscho) .
Veja commit f431d73 (25 Abr 2018) por Stefan Beller ( stefanbeller) .
Veja commit 2429335 (25 de abril de 2018) por Phillip Wood ( phillipwood) .
(Mesclado por Junio C Hamano - gitster- na confirmação 2c18e6a , 23 de maio de 2018)
pull: aceite --rebase-mergesrecriar a topologia da ramificação
Semelhante ao preservemodo simplesmente passando a --preserve-merges
opção para o rebasecomando, o mergesmodo simplesmente passa a
--rebase-mergesopção.
Isso permitirá que os usuários reorganizem convenientemente topologias de confirmação não triviais ao obter novas confirmações, sem achatá-las.
git rebaseAgora, a página de manual tem uma seção completa dedicada a refazer o histórico com mesclagens .
Extrair:
Existem razões legítimas pelas quais um desenvolvedor pode querer recriar confirmações de mesclagem: para manter a estrutura da ramificação (ou "topologia de confirmação") ao trabalhar em várias ramificações inter-relacionadas.
No exemplo a seguir, o desenvolvedor trabalha em uma ramificação de tópico que refatora a maneira como os botões são definidos e em outra ramificação de tópico que usa essa refatoração para implementar um botão "Relatar um bug".
A saída de git log --graph --format=%s -5pode ser assim:
* Merge branch 'report-a-bug'
|\
| * Add the feedback button
* | Merge branch 'refactor-button'
|\ \
| |/
| * Use the Button class for all buttons
| * Extract a generic Button class from the DownloadButton one
O desenvolvedor pode querer reestruturar essas confirmações para uma mais recente master
, mantendo a topologia da ramificação, por exemplo, quando se espera que a primeira ramificação do tópico seja integrada mastermuito antes do segundo, por exemplo, para resolver conflitos de mesclagem com alterações na
DownloadButtonclasse que foi feita em master.
Essa rebase pode ser realizada usando a --rebase-mergesopção
Consulte commit 1644c73 para um pequeno exemplo:
rebase-helper --make-script: introduza um sinalizador para refazer a mesclagem
O sequenciador acabou de aprender novos comandos destinados a recriar a estrutura de ramificações ( semelhante em espírito --preserve-merges, mas com um design substancialmente menos quebrado ).
Vamos permitir a rebase--helpergeração de listas de tarefas utilizando esses comandos, acionados pela nova --rebase-mergesopção.
Para uma topologia de consolidação como esta (em que o HEAD aponta para C):
- A - B - C (HEAD)
\ /
D
a lista de tarefas gerada ficaria assim:
# branch D
pick 0123 A
label branch-point
pick 1234 D
label D
reset branch-point
pick 2345 B
merge -C 3456 D # C
Qual é a diferença --preserve-merge?
O compromisso 8f6aed7 explica:
Era uma vez, este desenvolvedor aqui pensou: não seria bom se, digamos, os patches do Git for Windows no topo do núcleo, o Git pudessem ser representados como um emaranhado de ramificações e serem reestruturados no topo do núcleo do Git para manter um conjunto cereja-pick'able de série de patches?
A tentativa original para responder a esta era: git rebase --preserve-merges.
No entanto, esse experimento nunca teve a intenção de ser uma opção interativa, e apenas foi suportado git rebase --interactiveporque a implementação desse comando já parecia muito, muito familiar: foi projetada pela mesma pessoa que projetou --preserve-merges: a sua verdadeiramente.
E por "você realmente", o autor se refere a: Johannes Schindelin ( dscho) , que é o principal motivo (com alguns outros heróis - Hannes, Steffen, Sebastian, ...) de que temos o Git For Windows (embora de volta ao dia - 2009 - isso não foi fácil ).
Ele trabalha na Microsoft desde setembro de 2015 , o que faz sentido, considerando que a Microsoft agora usa fortemente o Git e precisa de seus serviços.
Essa tendência começou em 2013, na verdade, com o TFS . Desde então, a Microsoft gerencia o maior repositório Git do planeta ! E, desde outubro de 2018, a Microsoft adquiriu o GitHub .
Você pode ver Johannes falando neste vídeo para o Git Merge 2018 em abril de 2018.
Algum tempo depois, algum outro desenvolvedor (estou olhando para você, Andreas! ;-)) decidiu que seria uma boa ideia permitir --preserve-mergescombinar com --interactive(com advertências!) E o mantenedor do Git (bem, o mantenedor interino do Git durante a ausência de Junio, isto é) concordou, e foi aí que o glamour do --preserve-mergesdesign começou a desmoronar rapidamente e sem glamour .
Aqui Jonathan está falando sobre Andreas Schwab, de Suse.
Você pode ver algumas das discussões deles em 2012 .
O motivo? No --preserve-mergesmodo, os pais de uma consolidação de mesclagem (ou, de qualquer forma, de qualquer consolidação) não foram declarados explicitamente, mas estavam
implícitos no nome da consolidação passada para o pickcomando .
Isso tornou impossível, por exemplo, reordenar confirmações .
Sem mencionar a mudança de commits entre ramificações ou, deidade proibida, dividir ramificações de tópicos em duas.
Infelizmente, essas deficiências também impediram que o modo (cujo objetivo original era atender às necessidades do Git for Windows, com a esperança adicional de que também possa ser útil para outras pessoas) de atender às necessidades do Git for Windows.
Cinco anos depois, quando tornou-se realmente insustentável ter uma série de patches complicados e complicados de patches parcialmente relacionados e parcialmente não relacionados no Git for Windows, que eram reposicionados nas tags principais do Git de tempos em tempos (ganhando a ira imerecida do desenvolvedor) da git-remote-hgsérie malfadada
que obsoleta a primeira abordagem concorrente do Git for Windows, para depois ser abandonada sem mantenedor mais tarde) era realmente insustentável, nasceram as " tesouras de jardinagem Git " : um script, que acompanhava o rebase interativo, que determinaria primeiro a topologia de ramificação dos patches a serem rebaseados, criaria uma lista de pseudo-tarefas para edição adicional, transformaria o resultado em uma lista de tarefas real (fazendo uso pesado doexec comando para "implementar" os comandos da lista de tarefas ausentes) e, finalmente, recriar a série de patches sobre a nova confirmação de base.
(O script Git garden shears é mencionado neste patch no commit 9055e40 )
Isso foi em 2013.
E demorou cerca de três semanas para criar o design e implementá-lo como um script fora da árvore. Desnecessário dizer que a implementação precisou de alguns anos para estabilizar, enquanto o design em si se mostrava sólido.
Com este patch, a bondade das tesouras de jardim Git trata de git
rebase -isi .
Passar a --rebase-mergesopção gerará uma lista de tarefas que pode ser facilmente entendida e onde é óbvio como reorganizar as confirmações .
Novas ramificações podem ser introduzidas inserindo labelcomandos e chamando merge <label>.
E assim que esse modo se tornar estável e aceito universalmente, podemos descartar o erro de design que ocorreu--preserve-merges .
O Git 2.19 (terceiro trimestre de 2018) aprimora a nova --rebase-mergesopção, fazendo com que ela funcione --exec.
A --execopção " " para " git rebase --rebase-merges" colocou os comandos exec em locais errados, que foram corrigidos.
Consulte commit 1ace63b (09 de agosto de 2018) e commit f0880f7 (06 de agosto de 2018) por Johannes Schindelin ( dscho) .
(Mesclado por Junio C Hamano - gitster- in commit 750eb11 , 20 de agosto de 2018)
rebase --exec: faça funcionar com --rebase-merges
A idéia de --execé anexar uma execchamada após cada uma pick.
Desde a introdução do fixup!/ s quash!commits, essa idéia foi estendida para aplicar-se a "pick, possivelmente seguido de uma cadeia de correção / squash", ou seja, um executivo não seria inserido entre a picke qualquer uma de suas linhas fixupou correspondentes
squash.
A implementação atual usa um truque sujo para conseguir isso: assume que há apenas comandos pick / fixup / squash e, em seguida,
insere as execlinhas antes de qualquer um, pickexceto o primeiro, e anexa um final.
Com as listas de tarefas geradas por git rebase --rebase-merges, essa implementação simples mostra seus problemas: produz exatamente a coisa errada quando existem label, resete mergecomandos.
Vamos mudar a implementação para fazer exatamente o que queremos: procure
picklinhas, pule qualquer cadeia de correção / squash e insira a exec
linha . Espuma, enxágüe, repita.
Nota: nos esforçamos para inserir antes das linhas de comentário sempre que possível, pois confirmações vazias são representadas por linhas de seleção comentadas (e queremos inserir a linha executiva de uma seleção anterior antes dessa linha, e não depois).
Enquanto isso, adicione também execlinhas após mergecomandos, porque eles são semelhantes em espírito aos pickcomandos: eles adicionam novos commits.
O Git 2.22 (Q2 2019) corrige o uso de refs / reescrito / hierarquia para armazenar estados intermediários de rebase, o que faz inerentemente a hierarquia por árvore de trabalho.
Consulte commit b9317d5 , commit 90d31ff , commit 09e6564 ( 07/03/2019 ) por Nguyễn Thái Ngọc Duy ( pclouds) .
(Mesclado por Junio C Hamano - gitster- in commit 917f2cd , 09 abr 2019)
Verifique se refs / reescrito / é por árvore de trabalho
O a9be29c (sequenciador: make refs gerado pelo labelcomando worktree-local, 25/04/2018, Git 2.19) é adicionado refs/rewritten/como espaço de referência por worktree.
Infelizmente (infelizmente), existem alguns lugares que precisam de atualização para garantir que seja realmente por área de trabalho.
- add_per_worktree_entries_to_dir()é atualizado para garantir que a lista de referências analise por árvore de trabalho em refs/rewritten/vez de por árvore de repo.
common_list[]é atualizado para que git_path()retorne o local correto. Isso inclui " rev-parse --git-path".
Essa bagunça é criada por mim.
Comecei a tentar consertá-lo com a introdução de refs/worktree,onde todos os árbitros serão por área de trabalho sem tratamentos especiais.
Refs / reescritos infelizes vieram antes de refs / worktree, portanto é tudo o que podemos fazer.
Com o Git 2.24 (quarto trimestre de 2019), " git rebase --rebase-merges" aprendemos a conduzir diferentes estratégias de mesclagem e a passar opções específicas da estratégia para elas.
Veja commit 476998d (04 Set 2019) por Elijah Newren ( newren) .
Consulte confirmar e1fac53 , confirmar a63f990 , confirmar 5dcdd74 , confirmar e145d99 , confirmar 4e6023b , cometer f67336d , cometer a9c7107 , cometer b8c6f24 , cometer d51b771 , cometer c248d32 , cometer 8c1e240 , cometer 5efed0e , cometer 68b54f6 , cometer 2e7bbac , cometer 6180b20 , cometer d5b581f (31 Jul 2019) porJohannes Schindelin ( dscho) .
(Mesclado por Junio C Hamano - gitster- no commit 917a319 , 18 de setembro de 2019)
Com o Git 2.25 (primeiro trimestre de 2020), a lógica usada para diferenciar as referências locais e do repositório global da árvore de trabalho é corrigida, para facilitar a mesclagem de preservar.
Consulte commit f45f88b , commit c72fc40 , commit 8a64881 , commit 7cb8c92 , commit e536b1f (21 de outubro de 2019) por SZEDER Gábor ( szeder) .
(Incorporado por Junio C Hamano - gitster- in commit db806d7 , 10 nov 2019)
path.c: não chame a matchfunção sem valor emtrie_find()
Assinado por: SZEDER Gábor
'logs / refs' não é um caminho específico da árvore de trabalho, mas desde que o commit b9317d55a3 (verifique se refs / reescrito / é por worktree, 2019-03-07, v2.22.0-rc0) ' git rev-parse --git-path' está retornando um caminho falso se um final ' /' estiver presente:
$ git -C WT/ rev-parse --git-path logs/refs --git-path logs/refs/
/home/szeder/src/git/.git/logs/refs
/home/szeder/src/git/.git/worktrees/WT/logs/refs/
Usamos uma trieestrutura de dados para decidir com eficiência se um caminho pertence ao diretório comum ou se está trabalhando em uma árvore específica.
Como acontece b9317d55a3 acionou um bug que é tão antigo quanto a trieprópria implementação, adicionado em 4e09cf2acf (" path: otimizar verificação comum de diretórios", 31/08/2015, Git v2.7.0-rc0 - mesclagem listada no lote # 2 ).
De acordo com o comentário que descreve trie_find(), ele deve chamar apenas a função de correspondência fornecida 'fn' para um prefixo "/ -ou- \ 0 terminado da chave para a qual o trie contém um valor".
Isso não é verdade: há três lugares em que trie_find () chama a função match, mas um deles está faltando na verificação da existência do valor.
b9317d55a3 adicionou duas novas chaves ao trie:
- '
logs/refs/rewritten' e
- '
logs/refs/worktree', ao lado do já existente ' logs/refs/bisect'.
Isso resultou em um trienó com o caminho 'logs/refs/ ', que não existia antes e que não tinha um valor anexado.
Uma consulta para ' logs/refs/' localiza esse nó e, em seguida, acessa o local de chamada da matchfunção que não verifica a existência do valor e, portanto, chama a matchfunção com NULLcomo valor.
Quando a matchfunção check_common()é invocada com um NULLvalor, ela retorna 0, o que indica que o caminho consultado não pertence ao diretório comum, resultando no final do caminho falso mostrado acima.
Adicione a condição ausente a, trie_find()para que nunca invoque a função de correspondência com um valor inexistente.
check_common() não precisará mais verificar se obteve um valor diferente de NULL; portanto, remova essa condição.
Acredito que não existem outros caminhos que possam causar uma saída falsa semelhante.
AFAICT, a única outra chave que resulta na chamada da função de correspondência com um NULLvalor é ' co' (por causa das chaves 'common ' e ' config').
No entanto, como eles não estão em um diretório que pertence ao diretório comum, é esperado o caminho específico da árvore de trabalho resultante.
git --rebase-mergessubstituirá o antigogit --preserve-merges. Veja minha resposta abaixo