Isenção de responsabilidade: Eu uso o Git, sigo o desenvolvimento do Git na lista de discussão do git e até contribuo um pouco para o Git (principalmente o gitweb). Conheço o Mercurial pela documentação e alguns pela discussão no canal IRR #revctrl no FreeNode.
Obrigado a todas as pessoas no canal #mercurial IRC que forneceram ajuda sobre o Mercurial para esta redação
Sumário
Aqui seria bom ter alguma sintaxe para a tabela, algo como na extensão PHPMarkdown / MultiMarkdown / Maruku do Markdown
- Estrutura do repositório: O Mercurial não permite mesclagens de polvos (com mais de dois pais), nem marca objetos não confirmados.
- Tags: Mercurial usa
.hgtags
arquivo com versão com regras especiais para tags por repositório e também suporta tags locais em .hg/localtags
; As tags Git são refs que residem no refs/tags/
espaço para nome e, por padrão, são seguidas automaticamente na busca e requerem envio explícito.
- Ramos: No Mercurial, o fluxo de trabalho básico é baseado em cabeças anônimas ; O Git usa ramificações nomeadas leves e possui tipos especiais de ramificações (ramificações de rastreamento remoto ) que seguem ramificações no repositório remoto.
- Nomeação e intervalos de revisão : O Mercurial fornece números de revisão , local ao repositório e baseia as revisões relativas (contando desde a ponta, ou seja, ramificação atual) e os intervalos de revisão nessa numeração local ; O Git fornece uma maneira de se referir à revisão relativa à ponta da ramificação, e os intervalos de revisão são topológicos (com base no gráfico de revisões)
- O Mercurial usa o rastreamento de renomeação , enquanto o Git usa a detecção de renomeação para lidar com a renomeação de arquivos.
- Rede: o Mercurial suporta protocolos "inteligentes" SSH e HTTP e protocolo HTTP estático; O Git moderno suporta protocolos "inteligentes" SSH, HTTP e GIT e o protocolo "burro" HTTP (S). Ambos têm suporte para arquivos de pacotes configuráveis para transporte off-line.
- O Mercurial usa extensões (plugins) e API estabelecida; O Git possui capacidade de script e formatos estabelecidos.
Existem algumas coisas que diferem o Mercurial do Git, mas outras que os tornam semelhantes. Ambos os projetos tomam emprestado idéias um do outro. Por exemplo, o hg bisect
comando no Mercurial (anteriormente chamado de extensão de bissetriz ) foi inspirado pelo git bisect
comando no Git, enquanto a ideia de git bundle
foi inspirada no hg bundle
.
Estrutura do repositório, armazenando revisões
No Git, existem quatro tipos de objetos em seu banco de dados: objetos blob que contêm o conteúdo de um arquivo, objetos em árvore hierárquica que armazenam a estrutura de diretórios, incluindo nomes de arquivos e partes relevantes das permissões de arquivos (permissão executável para arquivos, sendo um link simbólico) , objeto de confirmação que contém informações de autoria, ponteiro para captura instantânea do estado do repositório na revisão representada por uma confirmação (por meio de um objeto em árvore do diretório principal do projeto) e referências a zero ou mais confirmações pai e marca objetos que referenciam outros objetos e podem ser assinado usando PGP / GPG.
O Git usa duas maneiras de armazenar objetos: formato livre , onde cada objeto é armazenado em um arquivo separado (esses arquivos são gravados uma vez e nunca modificados) e formato compactado , onde muitos objetos são armazenados compactados em delta em um único arquivo. A atomicidade das operações é fornecida pelo fato de que a referência a um novo objeto é gravada (atomicamente, usando o truque de criar + renomear) após a gravação de um objeto.
Os repositórios do Git requerem manutenção periódica usando git gc
(para reduzir o espaço em disco e melhorar o desempenho), embora atualmente o Git faça isso automaticamente. (Este método fornece uma melhor compactação de repositórios.)
Mercurial (tanto quanto eu o entendo) armazena o histórico de um arquivo em um registro de arquivos (juntos, eu acho, com metadados extras, como rastreamento de renomeação e algumas informações auxiliares); ele usa a estrutura plana chamada manifest para armazenar a estrutura do diretório e a estrutura chamada changelog que armazena informações sobre conjuntos de alterações (revisões), incluindo mensagem de confirmação e zero, um ou dois pais.
O Mercurial usa o diário de transações para fornecer atomicidade das operações e conta com o truncamento de arquivos para limpeza após operação com falha ou interrupção. Revlogs são apenas anexos.
Observando a estrutura do repositório no Git versus no Mercurial, pode-se ver que o Git se parece mais com um banco de dados de objetos (ou um sistema de arquivos endereçado a conteúdo) e o Mercurial mais como um banco de dados relacional de campo fixo tradicional.
Diferenças:
No Git, os objetos em árvore formam uma estrutura hierárquica ; no arquivo de manifesto Mercurial é estrutura plana . No objeto Blob Git, armazene uma versão do conteúdo de um arquivo; no Mercurial filelog armazena todo o histórico de um único arquivo (se não levarmos em conta aqui quaisquer complicações com renomeação). Isso significa que existem diferentes áreas de operações em que o Git seria mais rápido que o Mercurial, todas as outras coisas consideradas iguais (como mesclagens ou exibição do histórico de um projeto) e áreas em que o Mercurial seria mais rápido que o Git (como aplicação de patches ou exibição histórico de um único arquivo).Esse problema pode não ser importante para o usuário final.
Por causa da estrutura de registro fixo da estrutura do changelog do Mercurial , os commits no Mercurial podem ter apenas até dois pais ; commits no Git podem ter mais de dois pais (o chamado "polvo mesclado"). Embora você possa (em teoria) substituir a mesclagem de polvo por uma série de mesclagens com dois pais, isso pode causar complicações na conversão entre os repositórios Mercurial e Git.
Tanto quanto eu sei, o Mercurial não tem equivalente de tags anotadas (objetos de tag) do Git. Um caso especial de tags anotadas são tags assinadas (com assinatura PGP / GPG); O equivalente no Mercurial pode ser feito usando GpgExtension , cuja extensão está sendo distribuída junto com o Mercurial. Você não pode marcar objetos não confirmados no Mercurial como no Git, mas acho que isso não é muito importante (alguns repositórios git usam blob com tags para distribuir a chave pública do PGP e verificar as tags assinadas).
Referências: ramos e tags
No Git, as referências (ramificações, ramificações de rastreamento remoto e tags) residem fora do DAG de confirmações (como deveriam). Referências no refs/heads/
espaço para nome ( ramificações locais ) apontam para confirmações e geralmente são atualizadas por "git commit"; eles apontam para a ponta (cabeça) do galho, é por isso que esse nome. As referências no refs/remotes/<remotename>/
espaço para nome ( ramificações de rastreamento remoto ) apontam para confirmação, seguem ramificações no repositório remoto <remotename>
e são atualizadas por "git fetch" ou equivalente. As referências no refs/tags/
namespace ( tags ) apontam geralmente para confirmações (tags leves) ou objetos de tag (tags anotadas e assinadas) e não devem ser alteradas.
Tag
No Mercurial, você pode atribuir um nome persistente à revisão usando tag ; as tags são armazenadas de maneira semelhante aos padrões de ignorar. Isso significa que as tags visíveis globalmente são armazenadas em um .hgtags
arquivo controlado por revisão no seu repositório. Isso tem duas conseqüências: primeiro, o Mercurial precisa usar regras especiais para esse arquivo para obter a lista atual de todas as tags e atualizar esse arquivo (por exemplo, ele lê a revisão confirmada mais recentemente do arquivo, a versão não registrada no momento); segundo, você precisa confirmar as alterações nesse arquivo para ter uma nova tag visível para outros usuários / outros repositórios (tanto quanto eu o entendo).
O Mercurial também suporta tags locais , armazenadas em hg/localtags
, que não são visíveis para outras pessoas (e, é claro, não são transferíveis)
No Git, tags são referências fixas (constantes) nomeadas a outros objetos (geralmente objetos de tag, que por sua vez apontam para confirmações) armazenados no refs/tags/
espaço para nome. Por padrão, ao buscar ou empurrar um conjunto de revisões, o git busca ou envia automaticamente tags que apontam para revisões sendo buscadas ou enviadas por push. No entanto, você pode controlar até certo ponto quais tags são buscadas ou enviadas por push.
O Git trata tags leves (apontando diretamente para confirmações) e tags anotadas (apontando para objetos de tag, que contêm mensagem de tag que inclui opcionalmente assinatura PGP, que por sua vez apontam para confirmação) de maneira um pouco diferente, por exemplo, por padrão, considera apenas tags anotadas ao descrever confirma usando "git description".
O Git não possui um equivalente estrito de tags locais no Mercurial. No entanto, as práticas recomendadas do git recomendam configurar um repositório público vazio separado, no qual você envia alterações prontas e do qual outros clonam e buscam. Isso significa que as tags (e ramificações) que você não envia por push são privadas para o seu repositório. Por outro lado, você também pode usar um espaço para nome que não seja heads
, remotes
ou tags
, por exemplo, local-tags
para tags locais.
Opinião pessoal: na minha opinião, as tags devem residir fora do gráfico de revisão, pois são externas a ele (são indicadores do gráfico de revisões). As tags devem ser sem versão, mas transferíveis. A escolha da Mercurial de usar um mecanismo semelhante ao mecanismo para ignorar arquivos, significa que ele deve ser tratado .hgtags
especialmente (o arquivo na árvore é transferível, mas comum é versionado), ou possui tags apenas locais ( .hg/localtags
sem versão, intransferível).
Ramos
Na filial local do Git (ponta da ramificação ou cabeça da ramificação) é uma referência nomeada a uma confirmação, na qual é possível aumentar novas confirmações. Ramificação também pode significar linha de desenvolvimento ativa, ou seja, todas as confirmações alcançáveis a partir da ponta da ramificação. As ramificações locais residem no refs/heads/
espaço para nome, portanto, por exemplo, o nome completo da ramificação 'master' é 'refs / heads / master'.
A ramificação atual no Git (ou seja, ramificação com check-out e ramificação para onde a nova consolidação irá) é a ramificação que é referenciada pela referência HEAD. Pode-se ter HEAD apontando diretamente para um commit, em vez de ser uma referência simbólica; esta situação de estar em uma ramificação anônima e sem nome é chamada HEAD desanexada ("ramificação git" mostra que você está em '(sem ramificação)').
No Mercurial, existem ramificações anônimas (cabeças de ramificação), e é possível usar marcadores (via extensão de marcador ). Essas ramificações de favoritos são puramente locais e esses nomes (até a versão 1.6) não são transferíveis usando o Mercurial. Você pode usar rsync ou scp para copiar o .hg/bookmarks
arquivo em um repositório remoto. Você também pode usar hg id -r <bookmark> <url>
para obter o ID da revisão de uma dica atual de um marcador.
Desde 1,6 marcadores podem ser empurrados / puxados. A página BookmarksExtension possui uma seção sobre Trabalhando com repositórios remotos . Há uma diferença em que os nomes de favoritos do Mercurial são globais , enquanto a definição de 'remoto' no Git descreve também o mapeamento de nomes de ramificações dos nomes no repositório remoto para os nomes das ramificações locais de rastreamento remoto; por exemplo, refs/heads/*:refs/remotes/origin/*
mapeamento significa que é possível encontrar o estado da ramificação 'mestre' ('refs / heads / master') no repositório remoto no ramo de rastreamento remoto 'origin / master' ('refs / remotes / origin / master').
O Mercurial também denominou ramificações nomeadas , em que o nome da ramificação é incorporado em uma confirmação (em um conjunto de alterações). Esse nome é global (transferido na busca). Esses nomes de filiais são permanentemente registrados como parte dos metadados do conjunto de alterações. Com o Mercurial moderno, você pode fechar o "ramo nomeado" e parar de gravar o nome do ramo. Neste mecanismo, as dicas dos galhos são calculadas em tempo real.
Os "ramos nomeados" do Mercurial deveriam, em minha opinião, ser chamados de " commit labels" , porque é o que são. Há situações em que "ramificação nomeada" pode ter várias dicas (vários commits sem filhos) e também pode consistir em várias partes disjuntas do gráfico de revisões.
Não há equivalente a essas "ramificações incorporadas" do Mercurial no Git; além disso, a filosofia do Git é que, embora se possa dizer que o ramo inclui algum commit, isso não significa que um commit pertence a algum branch.
Observe que a documentação do Mercurial ainda propõe o uso de clones separados (repositórios separados) pelo menos para ramificações de longa duração (ramificação única por fluxo de trabalho do repositório), também conhecida como ramificação por clonagem .
Ramos em empurrar
Mercurial por padrão empurra todas as cabeças . Se você deseja enviar uma única ramificação ( cabeçote único ), é necessário especificar a revisão da ponta da ramificação que deseja enviar. Você pode especificar a dica da ramificação pelo número da revisão (local para o repositório), pelo identificador da revisão, pelo nome do marcador (local para o repositório, não é transferido) ou pelo nome da ramificação incorporada (ramificação nomeada).
Pelo que entendi, se você enviar uma série de revisões que contêm commits marcados como estando em algum "ramo nomeado" na linguagem Mercurial, você terá esse "ramo nomeado" no repositório para o qual envia. Isso significa que os nomes dessas ramificações incorporadas ("ramificações nomeadas") são globais (com relação aos clones de determinado repositório / projeto).
Por padrão (sujeito à push.default
variável de configuração), "git push" ou "git push < remote >" O Git enviaria ramificações correspondentes , ou seja, apenas as ramificações locais que já possuem seus equivalentes já presentes no repositório remoto que você envia. Você pode usar a --all
opção git-push ("git push --all") para enviar todos os branches , você pode usar "git push < remote > < branch >" para enviar um único ramo e usar "git push < remote > HEAD "para empurrar o ramo atual .
Tudo acima pressupõe que o Git não está configurado em quais ramificações enviar por meio de remote.<remotename>.push
variáveis de configuração.
Ramos na busca
Nota: aqui eu uso a terminologia Git, em que "buscar" significa fazer o download de alterações do repositório remoto sem integrar essas alterações ao trabalho local. É isso que " git fetch
" e " hg pull
" fazem.
Se entendi corretamente, por padrão, o Mercurial busca todas as cabeças do repositório remoto, mas você pode especificar a ramificação a ser buscada via " hg pull --rev <rev> <url>
" ou " hg pull <url>#<rev>
" para obter uma única ramificação . Você pode especificar <rev> usando o identificador de revisão, o nome "ramificação nomeada" (ramificação incorporada no log de alterações) ou o nome do marcador. No entanto, o nome do marcador (pelo menos atualmente) não é transferido. Todas as revisões de "ramificações nomeadas" que você recebe pertencem à transferência. "hg pull" armazena dicas de galhos que foram buscados como cabeças anônimas e sem nome.
No Git, por padrão (para controle remoto 'origin' criado por "git clone" e para controles remotos criados usando "git remote add") " git fetch
" (ou " git fetch <remote>
") obtém todas as ramificações do repositório remoto (do refs/heads/
espaço para nome) e as armazena em refs/remotes/
namespace. Isso significa, por exemplo, que a ramificação denominada 'mestre' (nome completo: 'refs / heads / master') na 'origem' remota seria armazenada (salva) como ramificação de rastreamento remoto 'origem / mestre' (nome completo: 'refs / controles remotos / origem / mestre ').
Você pode buscar uma única ramificação no Git usando git fetch <remote> <branch>
- O Git armazenaria ramificações solicitadas em FETCH_HEAD, que é algo semelhante às cabeças sem nome do Mercurial.
Esses são apenas exemplos de casos padrão da poderosa sintaxe refspec Git: com refspecs, você pode especificar e / ou configurar quais ramificações deseja buscar e onde armazená-las. Por exemplo, o caso "buscar todas as ramificações" padrão é representado por '+ refs / heads / *: refs / remotes / origin / *' curinga refspec, e "buscar uma ramificação única" é uma abreviação de 'refs / heads / <branch>:' . Refspecs são usados para mapear nomes de ramificações (refs) no repositório remoto para nomes de refs locais. Mas você não precisa saber (muito) sobre refspecs para poder trabalhar efetivamente com o Git (graças principalmente ao comando "git remote").
Opinião pessoal: Eu pessoalmente acho que "ramificações nomeadas" (com nomes de ramificações incorporadas nos metadados do conjunto de alterações) no Mercurial são um design equivocado com seu namespace global, especialmente para um sistema de controle de versão distribuído . Por exemplo, vamos considerar o caso em que Alice e Bob têm "ramificação nomeada" denominada 'for-joe' em seus repositórios, ramificações que não têm nada em comum. No repositório de Joe, no entanto, esses dois ramos seriam maltratados como um único ramo. Então, de alguma forma, você criou uma convenção que protege contra conflitos de nome de filial. Isso não é problema com o Git, onde, no repositório de Joe, o ramo 'for-joe' de Alice seria 'alice / for-joe', e de Bob seria 'bob / for-joe'.
Atualmente, os "ramos de favoritos" da Mercurial não possuem mecanismo de distribuição dentro do núcleo.
Diferenças:
Esta área é uma das principais diferenças entre Mercurial e Git, como James Woodyatt e Steve Losh disseram em suas respostas. Mercurial, por padrão, usa linhas de código leves anônimas, que em sua terminologia são chamadas de "cabeças". O Git usa ramificações nomeadas leves, com mapeamento injetivo para mapear nomes de ramificações no repositório remoto para nomes de ramificações de rastreamento remoto. O Git "força" você a nomear ramificações (bem, com exceção de ramificação única sem nome, situação chamada HEAD desanexada), mas acho que isso funciona melhor com fluxos de trabalho com ramificação pesada, como fluxo de trabalho de ramificação de tópico, significando várias ramificações no paradigma de repositório único.
Revisões de nomeação
No Git, existem muitas maneiras de nomear revisões (descritas, por exemplo, na página de manual git rev-parse ):
- O nome completo do objeto SHA1 (cadeia hexadecimal de 40 bytes) ou uma subseqüência desse tipo exclusivo no repositório
- Um nome simbólico de referência, por exemplo, 'mestre' (referindo-se à ramificação 'mestre') ou 'v1.5.0' (referindo-se à marca) ou 'origin / next' (referindo-se à ramificação de rastreamento remoto)
- Um
^
parâmetro de sufixo para revisão significa o primeiro pai de um objeto de confirmação, ^n
significa o nono pai de um commit de mesclagem. Um sufixo ~n
para o parâmetro de revisão significa o nono-antepassado de um commit na linha direta do primeiro pai. Esses sufixos podem ser combinados, para formar um especificador de revisão seguindo o caminho de uma referência simbólica, por exemplo, 'pu ~ 3 ^ 2 ~ 3'
- A saída de "git description", ou seja, uma tag mais próxima, opcionalmente seguida por um traço e um número de confirmações, seguida por um traço, um 'g' e um nome de objeto abreviado, por exemplo 'v1.6.5.1-75- g5bf8097 '.
Também existem especificadores de revisão envolvendo reflog, não mencionados aqui. No Git, cada objeto, seja ele commit, tag, tree ou blob, tem seu identificador SHA-1; existe uma sintaxe especial como, por exemplo, 'next: Documentation' ou 'next: README' para se referir à árvore (diretório) ou blob (conteúdo do arquivo) na revisão especificada.
O Mercurial também possui várias maneiras de nomear conjuntos de alterações (descritos, por exemplo, na página de manual hg ):
- Um número inteiro simples é tratado como um número de revisão. É preciso lembrar que os números de revisão são locais para um determinado repositório ; em outro repositório eles podem ser diferentes.
- Inteiros negativos são tratados como deslocamentos seqüenciais da ponta, com -1 denotando a ponta, -2 denotando a revisão anterior à dica e assim por diante. Eles também são locais para o repositório.
- Um identificador de revisão exclusivo (sequência hexadecimal de 40 dígitos) ou seu prefixo exclusivo.
- Um nome de tag (nome simbólico associado a uma determinada revisão), ou um nome de marcador (com extensão: nome simbólico associado a uma determinada cabeça, local ao repositório) ou um "ramo nomeado" (rótulo de confirmação; revisão dada por "ramo nomeado" é dica (confirmação sem filhos) de todas as confirmações com o rótulo de confirmação fornecida, com o maior número de revisão se houver mais de uma dica)
- O nome reservado "dica" é uma tag especial que sempre identifica a revisão mais recente.
- O nome reservado "nulo" indica a revisão nula.
- O nome reservado "." indica o pai do diretório de trabalho.
Diferenças
Como você pode ver nas listas acima, o Mercurial oferece números de revisão, locais para o repositório, enquanto o Git não. Por outro lado, o Mercurial oferece compensações relativas apenas de 'tip' (ramificação atual), local para o repositório (pelo menos sem ParentrevspecExtension ), enquanto o Git permite especificar qualquer confirmação após qualquer dica.
A revisão mais recente é denominada HEAD no Git e "tip" no Mercurial; não há revisão nula no Git. Tanto o Mercurial quanto o Git podem ter muitas raízes (podem ter mais de um commit sem pai; isso geralmente é resultado da junção de projetos anteriormente separados).
Veja também: Muitos tipos diferentes de especificadores de revisões no blog de Elijah (newren).
Opinião pessoal: acho que os números das revisões são superestimados (pelo menos no desenvolvimento distribuído e / ou histórico não-linear / ramificado). Primeiro, para um sistema de controle de versão distribuído, eles precisam ser locais para o repositório ou exigir o tratamento de algum repositório de maneira especial como uma autoridade central de numeração. Segundo, projetos maiores, com histórico mais longo, podem ter um número de revisões no intervalo de 5 dígitos, oferecendo apenas uma pequena vantagem sobre os identificadores de revisão reduzidos para 6-7 caracteres e implicando uma ordem estrita, enquanto as revisões são apenas parcialmente encomendadas (quero dizer aqui que as revisões n e n + 1 não precisam ser pai e filho).
Intervalos de revisão
No Git, os intervalos de revisão são topológicos . A A..B
sintaxe comumente vista , que para o histórico linear significa o intervalo de revisão começando em A (mas excluindo A) e terminando em B (ou seja, o intervalo é aberto a partir de baixo ), é uma abreviação ("açúcar sintático") para ^A B
, o que, para comandos que atravessam o histórico, significa tudo confirma acessível a partir de B, excluindo os acessíveis a partir de A. Isso significa que o comportamento do A..B
intervalo é totalmente previsível (e bastante útil), mesmo que A não seja ancestral de B: A..B
significa intervalo de revisões do ancestral comum de A e B (base de mesclagem ) à revisão B.
No Mercurial, os intervalos de revisão são baseados no intervalo dos números de revisão . O intervalo é especificado usando a A:B
sintaxe e, ao contrário do intervalo do Git, atua como um intervalo fechado . Também o intervalo B: A é o intervalo A: B em ordem inversa, o que não é o caso do Git (mas veja a nota abaixo na A...B
sintaxe). Mas essa simplicidade tem um preço: o intervalo de revisão A: B só faz sentido se A for ancestral de B ou vice-versa, ou seja, com história linear; caso contrário (acho que), o intervalo é imprevisível e o resultado é local no repositório (porque os números de revisão são locais no repositório).
Isso é corrigido com o Mercurial 1.6, que possui um novo intervalo de revisão topológica , em que 'A..B' (ou 'A :: B') é entendido como o conjunto de conjuntos de alterações que são descendentes de X e ancestrais de Y. Isso é , Eu acho, equivalente a '--ancestry-path A..B' no Git.
Git também possui notação A...B
para diferença simétrica de revisões; significa A B --not $(git merge-base A B)
, o que significa que todos os commits acessíveis a partir de A ou B, mas excluindo todos os commits acessíveis a partir de ambos (acessíveis a partir de ancestrais comuns).
Renomeia
O Mercurial usa o rastreamento de renomeação para lidar com as renomeações de arquivos. Isso significa que as informações sobre o fato de um arquivo ter sido renomeado são salvas no momento da confirmação; no Mercurial, essas informações são salvas no formulário "diff aprimorado" nos metadados do registro de arquivos (revogação de arquivos). A conseqüência disso é que você precisa usar hg rename
/ hg mv
... ou precisa se lembrar de executar hg addremove
para fazer a detecção de renomeação baseada em similaridade.
O Git é único entre os sistemas de controle de versão, pois usa a detecção de renomeação para lidar com as renomeações de arquivos. Isso significa que o fato de o arquivo ter sido renomeado é detectado no momento em que é necessário: ao fazer uma mesclagem ou ao mostrar um diff (se solicitado / configurado). Isso tem a vantagem de renomear o algoritmo de detecção e pode não ser congelado no momento da confirmação.
O Git e o Mercurial requerem o uso da --follow
opção para seguir as renomeações ao mostrar o histórico de um único arquivo. Ambos podem seguir os renomeamentos ao mostrar o histórico em linha de um arquivo em git blame
/ hg annotate
.
No Git, o git blame
comando é capaz de seguir o movimento do código, também movendo (ou copiando) o código de um arquivo para outro, mesmo que o movimento do código não faça parte da renomeação de arquivo saudável. Até onde eu sei, esse recurso é exclusivo do Git (no momento da redação, outubro de 2009).
Protocolos de rede
O Mercurial e o Git têm suporte para buscar e enviar para repositórios no mesmo sistema de arquivos, onde a URL do repositório é apenas um caminho do sistema de arquivos para o repositório. Ambos também têm suporte para buscar arquivos de pacote configurável .
Suporte mercurial buscando e enviando via SSH e via protocolos HTTP. Para o SSH, é necessário ter uma conta shell acessível na máquina de destino e uma cópia do hg instalada / disponível. Para acesso HTTP, o hg-serve
script Mercurial CGI ou em execução é necessário e o Mercurial precisa ser instalado na máquina do servidor.
O Git suporta dois tipos de protocolos usados para acessar o repositório remoto:
- Protocolos "inteligentes" , que incluem acesso via SSH e via protocolo git: // customizado (//
git-daemon
), exigem a instalação do git no servidor. A troca nesses protocolos consiste em cliente e servidor negociando sobre quais objetos eles têm em comum e, em seguida, gerando e enviando um pacote. O Git moderno inclui suporte ao protocolo HTTP "inteligente".
- Os protocolos "burros" , que incluem HTTP e FTP (apenas para busca) e HTTPS (para envio via WebDAV), não exigem o git instalado no servidor, mas exigem que o repositório contenha informações extras geradas por
git update-server-info
(geralmente executadas a partir de um gancho) ) A troca consiste em o cliente percorrer a cadeia de consolidação e fazer o download de objetos e arquivos de pacotes soltos, conforme necessário. A desvantagem é que ele baixa mais do que o estritamente necessário (por exemplo, no caso de canto, quando há apenas um único pacote, ele seria baixado inteiro, mesmo ao buscar apenas algumas revisões), e pode exigir muitas conexões para ser concluído.
Estendendo: capacidade de script vs extensões (plug-ins)
O Mercurial é implementado em Python , com alguns códigos principais escritos em C para desempenho. Ele fornece API para escrever extensões (plugins) como uma maneira de adicionar recursos extras. Algumas funcionalidades, como "ramificações de favoritos" ou revisões de assinatura, são fornecidas em extensões distribuídas com o Mercurial e requerem a ativação.
O Git é implementado nos scripts C , Perl e shell . O Git fornece muitos comandos de baixo nível ( encanamento ) adequados para uso em scripts. A maneira usual de introduzir um novo recurso é gravá-lo como Perl ou shell script, e quando a interface do usuário estabiliza, reescreva-o em C para desempenho, portabilidade e, no caso de shell script, evitando casos de canto (esse procedimento é chamado de builtinification ).
O Git confia e é construído em torno dos formatos [repositório] e protocolos [rede]. Em vez de ligações de idiomas, há reimplementações (parciais ou completas) do Git em outros idiomas (alguns deles são parcialmente reimplementações e parcialmente wrappers em torno dos comandos git): JGit (Java, usado por EGit, Eclipse Git Plugin), Grit (Ruby) , Dulwich (Python), git # (C #).
TL; DR