Git e Mercurial - Compare e Contraste

520

Por um tempo agora eu tenho usado o subversion para meus projetos pessoais.

Cada vez mais, continuo ouvindo grandes coisas sobre Git e Mercurial e DVCS em geral.

Eu gostaria de dar uma guinada na coisa toda do DVCS, mas não estou muito familiarizado com nenhuma das opções.

Quais são algumas das diferenças entre Mercurial e Git?

Nota: Eu estou não tentando descobrir qual é o "melhor" ou mesmo que eu deveria começar. Estou procurando principalmente áreas-chave onde elas são semelhantes e onde são diferentes, porque estou interessado em saber como elas diferem em termos de implementação e filosofia.

TM.
fonte

Respostas:

451

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 .hgtagsarquivo 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 bisectcomando no Mercurial (anteriormente chamado de extensão de bissetriz ) foi inspirado pelo git bisectcomando no Git, enquanto a ideia de git bundlefoi 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 .hgtagsarquivo 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, remotesou tags, por exemplo, local-tagspara 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 .hgtagsespecialmente (o arquivo na árvore é transferível, mas comum é versionado), ou possui tags apenas locais ( .hg/localtagssem 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/bookmarksarquivo 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.defaultvariá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 --allopçã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, ^nsignifica o nono pai de um commit de mesclagem. Um sufixo ~npara 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..Bsintaxe 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..Bintervalo é totalmente previsível (e bastante útil), mesmo que A não seja ancestral de B: A..Bsignifica 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:Bsintaxe 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...Bsintaxe). 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...Bpara 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 addremovepara 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 --followopçã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 blamecomando é 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-servescript 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

Jakub Narębski
fonte
32
O que se pode acrescentar é que o hg tenta muito desencorajar a reescrita do histórico (isso só pode ser feito com extensões: mq, histedit, rebase), enquanto o git o faz pronto para uso (e parece parte da comunidade até incentiva).
tonfa
80
Eu acho que "reescrever a história" é desnecessariamente negativo. O que eu encorajo no git é que as pessoas considerem a história que publicam. Outras pessoas precisam consumir essa história. Ninguém (nem você) está interessado em todos os seus "oops, esqueci um arquivo" confirma. Ninguém se importa com a série de fusões de entrada pelas quais você passou enquanto estava rastreando uma ramificação upstream enquanto trabalhava em um novo recurso. Esse tipo de coisa torna a história (e as ferramentas relacionadas) muito mais difíceis de entender e não oferece valor.
Dustin
5
@ Jakub: branches nomeados são algo que não existe no git. É simplesmente um campo na descrição do cset (e isso faz parte da história, por isso é imutável, a menos que você altere hashes, etc.). Algo como as ramificações git são marcadores ("cabeças nomeadas"), mas atualmente não são transferíveis remotamente (você não importa os marcadores remotos ao puxar). stevelosh.com/blog/entry/2009/8/30/… explica muito bem.
tonfa
28
"O Mercurial originalmente suportava apenas uma ramificação por fluxo de trabalho do repositório, e isso mostra." Oh não. O Mercurial não suportava ramificações nomeadas originalmente, mas você sempre foi capaz de ter tantas ramificações anônimas quanto seu coração deseja em um único repositório. Compare isso com o git, o que torna a ramificação anônima uma grande dor. Você praticamente tem que pensar em um nome para cada pequeno ramo, se quiser fazer alguma coisa (e evitar ter seu lixo coletado).
9788 Steve Losh
17
@ SteveLosh: você parece achar que ter muitos ramos anônimos no Mercurial é uma coisa boa, mas para mim parece horrível. Como você os diferencia? E você parece achar que a nomeação de ramificações no Git é uma dificuldade enorme, mas se você tiver um propósito para criar a ramificação, terá um nome pronto. Se você não tem um propósito, não faça ramificações. Não vejo como a Mercurial oferece algum benefício aqui. Só vejo dor e confusão.
Iconoclast
57

Eu acho que você pode ter uma ideia de como esses sistemas são semelhantes ou diferentes ao gravar esses dois vídeos:

Linus Torvalds no Git ( http://www.youtube.com/watch?v=4XpnKHJAok8 )
Bryan O'Sullivan no Mercurial ( http://www.youtube.com/watch?v=JExtkqzEoHY )

Ambos são muito semelhantes em design, mas muito diferentes em implementações.

Eu uso o Mercurial. Tanto quanto eu entendo o Git, uma coisa importante é que o git é diferente: ele rastreia o conteúdo dos arquivos em vez dos próprios arquivos. Linus diz que, se você mover uma função de um arquivo para outro, o Git mostrará o histórico dessa única função ao longo da movimentação.

Eles também dizem que o git é mais lento em relação ao HTTP, mas tem seu próprio protocolo de rede e servidor.

O Git funciona melhor como um cliente espesso SVN do que o Mercurial. Você pode puxar e enviar contra um servidor SVN. Essa funcionalidade ainda está em desenvolvimento no Mercurial

Tanto o Mercurial quanto o Git têm ótimas soluções de hospedagem disponíveis na Web (BitBucket e GitHub), mas o Google Code suporta apenas o Mercurial. A propósito, eles têm uma comparação muito detalhada do Mercurial e do Git para decidir qual deles oferecer suporte ( http://code.google.com/p/support/wiki/DVCSAnalysis ). Tem muitas informações boas.

artemb
fonte
8
Eu recomendo a leitura de todos os comentários nessa página de código do Google. As informações parecem um pouco tendenciosas e não correspondem bem à minha experiência. Eu gosto de hg e usei bastante por um ano ou mais. Eu uso o git quase exclusivamente agora. Há coisas que preciso realizar para que o git facilite e o hg torne quase impossível (embora alguns gostem de chamar isso por meio de "complicação".) O git básico é tão fácil quanto o hg base.
Dustin
11
Dustin, talvez liste alguns desses casos "git easy, hg nem tanto"?
Gregg Lind
1
@knittl não, não. Principalmente porque seria difícil para eles implantá-lo, já que o git não possui um protocolo http inteligente (a maioria dos front-ends do Google é baseada em http).
tonfa
2
@tonfa: Atualmente, o protocolo HTTP inteligente para Git está sendo desenvolvido (como em: há correções na lista de discussão do git e elas estão em 'pu' = ramificação de atualizações propostas no repositório git.git).
Jakub Narębski 21/10/09
4
A partir de agora, o Google Code também suporta o Git.
precisa saber é o seguinte
30

Escrevi uma entrada de blog sobre os modelos de ramificação do Mercurial há algum tempo e incluí comparações com o modelo de ramificação do git. Talvez você ache interessante: http://stevelosh.com/blog/entry/2009/8/30/a-guide-to-branching-in-mercurial/

Steve Losh
fonte
@ Steve Losh: Eu queria comentar sobre esta entrada do blog (sobre ramo não nomeado, também conhecido como HEAD desanexado, e sobre o git-fetch buscando todos os ramos, não um), mas recebi um erro de 500 servidores.
Jakub Narębski 21/10/09
1
@Jakub Narębski Aposto que o problema é o caractere não ASCII do seu nome. Tenho certeza de que encontrei o mesmo problema em outro site e a ligação do Python Askimet é bloqueada no Unicode. Vou dar uma olhada.
21710 Steve Losh
@ Steve Losh: Obrigado por uma informação, depois de "unidecoding" meu nome, eu era capaz de postar um comentário. Descrição muito boa de ramificação em Mercurial (mas eu ainda acho que é inferior ;-))
Jakub Narębski
@SteveLosh Convido você a expandir esta resposta para uma revisão mais completa do mercurial. No momento, infelizmente, a resposta principal é em grande parte um anúncio para o git, porque seu autor não usou muito o mercurial e não entende como usá-lo de maneira eficaz. Seria bom que outra resposta fornecesse o ponto de vista mercurial, por assim dizer.
21815 Warren Dew
25

Eu uso os dois regularmente. A principal diferença funcional está na maneira como os nomes Git e Mercurial se ramificam nos repositórios. Com o Mercurial, os nomes das ramificações são clonados e puxados junto com seus conjuntos de alterações. Quando você adiciona alterações a uma nova ramificação no Mercurial e envia para outro repositório, o nome da ramificação é enviado ao mesmo tempo. Portanto, os nomes das filiais são mais ou menos globais no Mercurial, e você precisa usar a extensão Bookmark para ter nomes leves apenas locais (se você quiser; o Mercurial, por padrão, usa linhas de código leves anônimas, que em sua terminologia são chamados "cabeças"). No Git, os nomes das ramificações e seu mapeamento injetivo para ramificações remotas são armazenados localmente e você deve gerenciá-los explicitamente, o que significa saber como fazer isso.

Como outros observarão aqui, há muitas e pequenas diferenças. A coisa com os galhos é o grande diferencial.

James Woodyatt
fonte
2
Veja também este post para uma boa explicação sobre os quatro tipos de filiais no Mercurial: stevelosh.com/blog/entry/2009/8/30/…
Martin Geisler
19

Dê uma olhada no Git vs. Mercurial: relaxe no blog de Patrick Thomson, onde ele escreve:
Git é MacGyver , Mercurial é James Bond

Observe que esta postagem do blog é de 7 de agosto de 2008 e os dois SCM melhoraram muito desde então.

Jakub Narębski
fonte
11

Mercurial é quase totalmente escrito em python. O núcleo do Git é escrito em C (e deve ser mais rápido que o Mercurial) e as ferramentas escritas em sh, perl, tcl e usa utilitários GNU padrão. Portanto, ele precisa trazer todos esses utilitários e intérpretes para um sistema que não os contenha (por exemplo, Windows).

Ambos suportam o trabalho com o SVN, embora o suporte ao AFAIK svn esteja quebrado para o git no Windows (pode ser que eu seja apenas azarado / coxo, quem sabe). Também existem extensões que permitem interoperar entre git e Mercurial.

O Mercurial possui uma ótima integração com o Visual Studio . Na última vez que verifiquei, o plugin para Git estava funcionando, mas extremamente lento.

Os conjuntos de comandos básicos são muito semelhantes (init, clone, add, status, commit, push, pull etc.). Portanto, o fluxo de trabalho básico será o mesmo. Além disso, existe um cliente semelhante ao TortoiseSVN para ambos.

As extensões do Mercurial podem ser escritas em python (sem surpresa!) E, para o git, podem ser escritas em qualquer forma executável (binário executável, shell script etc). Algumas extensões são muito poderosas, como git bisect.

elder_george
fonte
9
O núcleo mercurial é escrito em C também FYI (mas provavelmente é um núcleo menor que o git).
tonfa
1
Eu uso o git-svn no Windows sem nenhum problema. Está usando o Cygwin (a única maneira correta de usar o git no Windows, se você me perguntar). Não posso falar por msysgit.
21139 Dan Molding
@ Dan Molding: Sim, tive problemas com o msysgit. Talvez precise tentar a porta cygwin (eu tive uma experiência ruim com o cygwin anteriormente, então evitei). Obrigado pelo conselho!
elder_george
Pessoalmente, não gosto da intrusão do cygwin no registro para armazenar dados do usuário. É uma PITA fazê-lo executar a chave USB e manter uma cópia local da unidade c: \ sincronizada para quando eu quiser executar mais rápido do que minha chave USB pode executar. : - /
Chris K
1
Eu uso o plug-in Git para o Visual Studio mencionado acima, e o desempenho da versão atual é bom. Ele é direcionado às ferramentas da linha de comando para fazer o trabalho, portanto, não acho que perderá significativamente o desempenho em grandes projetos.
Stuart Ellis
11

Se você precisar de um bom suporte do Windows, poderá preferir o Mercurial. O TortoiseHg (plugin do Windows Explorer) consegue oferecer uma interface gráfica simples de usar para uma ferramenta bastante complexa. Como estado aqui, você também terá um plug-in do Visual Studio . No entanto, da última vez que tentei, a interface SVN não funcionou tão bem no Windows.

Se você não se importa com a interface da linha de comando, eu recomendaria o Git. Não por razões técnicas, mas por razões estratégicas. A taxa de adoção do git é muito maior. Veja quantos projetos de código aberto famosos estão mudando de cvs / svn para Mercurial e quantos estão mudando para Git. Veja quantos fornecedores de hospedagem de código / projeto você pode encontrar com suporte ao git em comparação com a hospedagem Mercurial.

Eric Darchis
fonte
Há também o TortoiseGit, se você não gosta de usar a linha de comando. (Mas isso requer msysgit para ser instalado.)
Ben James
2
Nossa empresa acabou escolhendo o git por causa de seu excelente suporte no Windows - confira Git Extensions . Sou tendencioso porque agora sou colaborador, mas não era quando começamos a usá-lo.
Jacob Stanley
11

Depois de ler tudo sobre o Mercurial, é mais fácil (o que eu ainda acredito, depois que toda a comunidade da Internet é de opinião), quando comecei a trabalhar com o Git e o Mercurial, senti que o Git é relativamente mais simples para me adaptar (comecei Mercurial com TortoiseHg) ao trabalhar na linha de comando, principalmente porque os comandos git foram nomeados adequadamente de acordo com mim e são menos numerosos. O Mercurial possui nomes diferentes para cada comando que executa um trabalho distinto, enquanto os comandos Git podem ser multiuso de acordo com a situação (por exemplo,checkout) Embora o Git fosse mais difícil na época, agora a diferença não é substancial. YMMV .. Com um bom cliente GUI como o TortoiseHg, é verdade que era muito mais fácil trabalhar com o Mercurial e não precisava me lembrar dos comandos um pouco confusos. Não vou detalhar como cada comando para a mesma ação variou, mas aqui estão duas listas abrangentes: 1 do próprio site da Mercurial e e2 da wikivs .

╔═════════════════════════════╦════════════════════════════════════════════════════════════════════════════════════════════════╗
║           Git               ║                Mercurial                                                                       ║
╠═════════════════════════════╬════════════════════════════════════════════════════════════════════════════════════════════════╣
║ git pull                    ║ hg pull -u                                                                                     ║
║ git fetch                   ║ hg pull                                                                                        ║
║ git reset --hard            ║ hg up -C                                                                                       ║
║ git revert <commit>         ║ hg backout <cset>                                                                              ║
║ git add <new_file>          ║ hg add <new_file> (Only equivalent when <new_file> is not tracked.)                            ║
║ git add <file>              ║ Not necessary in Mercurial.                                                                    ║
║ git add -i                  ║ hg record                                                                                      ║
║ git commit -a               ║ hg commit                                                                                      ║
║ git commit --amend          ║ hg commit --amend                                                                              ║
║ git blame                   ║ hg blame or hg annotate                                                                        ║
║ git blame -C                ║ (closest equivalent): hg grep --all                                                            ║
║ git bisect                  ║ hg bisect                                                                                      ║
║ git rebase --interactive    ║ hg histedit <base cset> (Requires the HisteditExtension.)                                      ║
║ git stash                   ║ hg shelve (Requires the ShelveExtension or the AtticExtension.)                                ║
║ git merge                   ║ hg merge                                                                                       ║
║ git cherry-pick <commit>    ║ hg graft <cset>                                                                                ║
║ git rebase <upstream>       ║ hg rebase -d <cset> (Requires the RebaseExtension.)                                            ║
║ git format-patch <commits>  ║ hg email -r <csets> (Requires the PatchbombExtension.)                                         ║
║   and git send-mail         ║                                                                                                ║
║ git am <mbox>               ║ hg mimport -m <mbox> (Requires the MboxExtension and the MqExtension. Imports patches to mq.)  ║
║ git checkout HEAD           ║ hg update                                                                                      ║
║ git log -n                  ║ hg log --limit n                                                                               ║
║ git push                    ║ hg push                                                                                        ║
╚═════════════════════════════╩════════════════════════════════════════════════════════════════════════════════════════════════╝

O Git salva internamente um registro de todas as versões de arquivos confirmados, enquanto o Hg salva apenas os conjuntos de alterações que podem ter uma área menor. O Git facilita a alteração da história em comparação com o Hg, mas, novamente, é um recurso de ódio ou amor. Eu gosto de Hg para o primeiro e Git para o segundo.

O que sinto falta no Hg é o recurso do submódulo do Git. Hg tem subrepos, mas esse não é exatamente o submódulo Git.

O ecossistema em torno dos dois também pode influenciar a escolha de alguém: o Git precisa ser mais popular (mas isso é trivial), o Git tem o GitHub, enquanto o Mercurial tem o BitBucket , o Mercurial tem o TortoiseHg, para o qual eu não vi um equivalente tão bom para o Git.

Cada um tem suas vantagens e desvantagens, com um deles que você não vai perder.

nawfal
fonte
8

Confira o post de Scott Chacon há algum tempo.

Eu acho que o git tem uma reputação de ser "mais complicado", embora na minha experiência não seja mais complicado do que precisa ser. Na IMO, o modelo git é muito mais fácil de entender (as tags contêm confirmações (e ponteiros para zero ou mais confirmações pai) contêm árvores contêm blobs e outras árvores ... concluídas).

Não é apenas minha experiência que o git não é mais confuso do que mercurial. Eu recomendo ler novamente este post de Scott Chacon sobre o assunto.

Dustin
fonte
1
O modelo mercurial é quase idêntico: os pontos do changelog para manifestar apontam para arquivo de revisões / blob ... feito. Se você estava comparando o formato em disco, provavelmente não considerou o arquivo de pacotes mais complicado de explicar do que o simples formato de revlog da hg.
tonfa
Bem, esse modelo simplificado ignora a marcação, que é consideravelmente mais desajeitada na prática em hg (embora eu argumente que a tag git é um pouco confusa porque não cria um objeto de tag por padrão). O formato em disco era particularmente caro para os dois projetos que tinham um histórico de muitos nomes de arquivos.
Dustin
1
Não acho que o modelo ignore a marcação: a marcação é trivial no Mercurial - como você sabe, é apenas um arquivo que dá nomes aos hashes SHA-1. Não há adivinhação sobre como as tags fluem pelo sistema: elas se movem junto com empurrões e puxões. E se houver um conflito de tags, bem, também é trivial resolvê-lo: você o soluciona como qualquer outro conflito. Afinal, é apenas uma linha em um arquivo de texto. Eu acho que a simplicidade deste modelo é um recurso muito bom.
Martin Geisler
Dustin: Sim, os usuários geralmente ficam confusos pelo fato de você não poder ver a tag 1.0 .hgtagsquando faz o check-out da revisão 1.0. No entanto, você não precisa olhar para dentro .hgtagse verá que hg tagsainda lista todas as tags. Além disso, esse comportamento é uma consequência simples do armazenamento de tags em um arquivo controlado por versão - novamente o modelo é fácil de entender e muito previsível .
9133 Martin Geisler
1
Martin Geisler Eu argumentaria que as regras para tags no Mercurial, necessárias porque usam arquivos controlados por versão para transporte, com camada de regras especiais para tornar as tags sem versão, são tudo menos fáceis de entender.
Jakub Narębski 24/10/09
5

Eu uso o Git há pouco mais de um ano no meu trabalho atual e, antes disso, usei o Mercurial por um pouco mais de um ano no meu trabalho anterior. Vou fornecer uma avaliação da perspectiva do usuário.

Primeiro, ambos são sistemas de controle de versão distribuídos. Os sistemas de controle de versão distribuído requerem uma mudança de mentalidade em relação aos sistemas de controle de versão tradicionais, mas na verdade funcionam muito melhor de várias maneiras, quando os entendemos. Por esse motivo, considero o Git e o Mercurial muito superiores ao Subversion, Perforce etc. A diferença entre os sistemas de controle de versão distribuído e os sistemas tradicionais de controle de versão é muito maior que a diferença entre o Git e o Mercurial.

No entanto, também existem diferenças significativas entre o Git e o Mercurial que tornam cada um mais adequado ao seu próprio subconjunto de casos de uso.

Mercurial é mais simples de aprender. Cheguei ao ponto em que raramente tinha que me referir à documentação ou anotações após algumas semanas de uso do Mercurial; Ainda tenho que me referir às minhas anotações regularmente com o Git, mesmo depois de usá-lo por um ano. Git é consideravelmente mais complicado.

Isso ocorre em parte porque o Mercurial é simplesmente mais limpo. Você raramente precisa ramificar manualmente no Mercurial; O Mercurial criará uma filial anônima automaticamente para você, se e quando você precisar. A nomenclatura mercurial é mais intuitiva; você não precisa se preocupar com a diferença entre "buscar" e "puxar", como faz com o Git. Mercurial é um pouco menos buggy. Existem problemas de distinção entre maiúsculas e minúsculas nos nomes de arquivos que costumavam causar problemas ao enviar projetos entre plataformas com Git e Mercurial; isso foi corrigido no Mercurial há algum tempo, enquanto não havia sido corrigido no Git pela última vez que verifiquei. Você pode informar ao Mercurial sobre renomeação de arquivos; com o Git, se ele não detectar a renomeação automaticamente - uma proposta muito acertada ou perdida na minha experiência - a renomeação não poderá ser rastreada.

A outra razão para a complicação adicional do Git, no entanto, é que muito disso é necessário para suportar recursos e energia adicionais. Sim, é mais complicado lidar com ramificações no Git - mas, por outro lado, depois de ter as ramificações, não é muito difícil fazer coisas com essas ramificações que são praticamente impossíveis no Mercurial. Rebasear ramificações é uma dessas coisas: você pode mover sua ramificação para que sua base, em vez de ser o estado do tronco quando você ramificou, seja o estado do tronco agora; isso simplifica bastante o histórico da versão quando há muitas pessoas trabalhando na mesma base de código, já que cada um dos impulsos no tronco pode parecer sequencial, em vez de entrelaçado. Da mesma forma, é muito mais fácil recolher vários commit no seu branch em um único commit,

Por fim, acho que a escolha entre Mercurial e Git deve depender do tamanho dos seus projetos de controle de versão, medidos em termos do número de pessoas trabalhando neles simultaneamente. Se você tem um grupo de uma dúzia ou mais trabalhando em um único aplicativo da web monolítico, por exemplo, as ferramentas mais poderosas de gerenciamento de filiais do Git o tornarão um ajuste muito melhor para o seu projeto. Por outro lado, se sua equipe estiver desenvolvendo um sistema distribuído heterogêneo, com apenas um ou dois desenvolvedores trabalhando em um componente de cada vez, o uso de um repositório Mercurial para cada um dos projetos de componentes permitirá que o desenvolvimento prossiga de maneira mais suave com menos sobrecarga de gerenciamento de repositório.

Conclusão: se você tem uma grande equipe desenvolvendo um único aplicativo enorme, use o Git; se seus aplicativos individuais forem pequenos, com qualquer escala proveniente do número e não do tamanho desses aplicativos, use o Mercurial.

Warren Dew
fonte
4

Uma diferença totalmente não relacionada aos DVCSs:

O Git parece ser muito popular entre os desenvolvedores C. O Git é o repositório de fato do Kernel Linux e esse pode ser o motivo pelo qual ele é tão popular entre os desenvolvedores C. Isto é especialmente verdade para aqueles que têm o luxo de trabalhar apenas no mundo Linux / Unix.

Os desenvolvedores de Java parecem preferir o Mercurial ao invés do Git. Há possivelmente duas razões para isso: uma é que vários projetos Java muito grandes estão hospedados no Mercurial, incluindo o próprio JDK. Outra é que a estrutura e a documentação limpa do Mercurial atraem pessoas provenientes do campo Java, enquanto essas pessoas acham o Git inconsistente nos nomes dos comandos wrt e carecem de documentação. Não estou dizendo que isso seja verdade, estou dizendo que as pessoas se acostumaram com algo do seu habitat habitual e então tendem a escolher o DVCS a partir disso.

Os desenvolvedores de Python favorecem quase exclusivamente o Mercurial, eu diria. Na verdade, não há nenhuma razão racional para isso além do fato de o Mercurial ser baseado em Python. (Também uso o Mercurial e realmente não entendo por que as pessoas se preocupam com a linguagem de implementação do DVCS. Não entendo uma palavra do Python e se não fosse pelo fato de estar listado em algum lugar é baseado em Python, então eu não saberia).

Eu não acho que você possa dizer que um DVCS se encaixa em um idioma melhor que outro, então você não deve escolher isso. Mas, na realidade, as pessoas escolhem (parcialmente) com base em quais DVCS ficam mais expostos como parte de sua comunidade.

(não, não tenho estatísticas de uso para fazer backup de minhas reivindicações acima .. tudo é baseado na minha própria subjetividade)

peterh
fonte