Por que todo repositório sério do Github que recebo solicita que eu comprima meus commits em um único commit?
Eu pensei que o log do git estava lá para que você pudesse inspecionar todo o seu histórico e ver exatamente quais mudanças aconteceram onde, mas esmagá-lo o puxa para fora do histórico e agrupa tudo em um commit. Qual é o ponto?
Isso também parece ir contra o mantra "comprometer-se cedo e comprometer-se com frequência".
Respostas:
Para que você tenha um histórico do Git claro e conciso, que documente de forma clara e fácil as alterações feitas e os motivos.
Por exemplo, um log git típico 'sem interrupção' para mim pode se parecer com o seguinte:
Que bagunça!
Enquanto um log git gerenciado e mesclado com mais cuidado, com um pouco de foco adicional nas mensagens para isso, pode parecer:
Eu acho que você pode ver o ponto de esmagar os commits em geral e o mesmo princípio se aplica aos pedidos de pull - Legibilidade da História. Você também pode adicionar um log de confirmação que já possui centenas ou mesmo milhares de confirmações e isso ajudará a manter o histórico de crescimento curto e conciso.
Você quer se comprometer cedo e com frequência. É uma prática recomendada por vários motivos. Acho que isso me leva a ter confirmações frequentes que são "wip" (trabalho em andamento) ou "parte A concluída" ou "erro tipográfico, correção menor" em que estou usando o git para me ajudar a trabalhar e fornecer pontos de trabalho que Posso voltar para se o código a seguir não estiver funcionando conforme progredir para que as coisas funcionem. No entanto, eu não preciso ou quero esse histórico como parte do histórico final do git, para que eu possa reprimir meus commits - mas veja as notas abaixo sobre o que isso significa em um ramo de desenvolvimento vs. mestre.
Se houver marcos importantes que representam estágios de trabalho distintos, ainda é aceitável ter mais de um commit por recurso / tarefa / bug. No entanto, isso geralmente destaca o fato de que o ticket em desenvolvimento é 'muito grande' e precisa ser dividido em partes menores que podem ser independentes, por exemplo:
parece "1 trabalho". Ou eles existem ou não! Não parece fazer sentido divulgá-lo. No entanto, a experiência me mostrou que (dependendo do tamanho e da complexidade da organização) um caminho mais granular pode ser:
Peças pequenas significam revisões de código mais fáceis, testes de unidade mais fáceis, melhor oportunidade de qa, melhor alinhamento ao Princípio de Responsabilidade Única, etc.
Para os aspectos práticos de quando realmente fazer essas abóboras, existem basicamente dois estágios distintos que têm seu próprio fluxo de trabalho
Durante o seu desenvolvimento, você confirma 'cedo e frequentemente' e com mensagens rápidas 'descartáveis'. Você pode esmagar aqui algumas vezes, por exemplo, esmagar em confirmações de mensagens wip e todo. Tudo bem, dentro da ramificação, manter várias confirmações que representam etapas distintas que você fez no desenvolvimento. A maioria das abóboras que você escolhe fazer deve estar dentro desses ramos de recursos, enquanto eles estão sendo desenvolvidos e antes da mesclagem para dominar.
Ao adicionar à ramificação da linha principal, você deseja que as confirmações sejam concisas e formatadas corretamente de acordo com o histórico da linha principal existente. Isso pode incluir o ID do sistema do Ticket Tracker, por exemplo, o JIRA, como mostrado nos exemplos. O esmagamento não se aplica aqui, a menos que você queira 'acumular' vários commits distintos no master. Normalmente você não.
O uso
--no-ff
ao mesclar para o mestre usará uma confirmação para a mesclagem e também preservará o histórico (na ramificação). Algumas organizações consideram isso uma prática recomendada. Veja mais em https://stackoverflow.com/q/9069061/631619 Você também verá o efeito prático emgit log
que um--no-ff
commit será o último commit, na parte superior do HEAD (quando terminar), enquanto que sem--no-ff
ele pode ser mais abaixo na história, dependendo das datas e outras confirmações.fonte
Como muitas vezes a pessoa que puxa um PR se preocupa com o efeito líquido dos commits "recurso adicional X", não com os "modelos básicos, função X de correção de erros, função Y de adição, adição de função Y, erros de digitação corrigidos nos comentários, parâmetros ajustados de escala de dados, mapa de hash tem melhor desempenho do que" lista "... nível de detalhe
Se você acha que suas 16 confirmações são melhor representadas por 2 confirmações, em vez de 1 "Adicionado recurso X, Z re-fatorado para usar X", então provavelmente é bom propor um PR com 2 confirmações, mas talvez seja melhor propor 2 PRs separados nesse caso (se o representante ainda insistir em PRs de confirmação única)
Isso não vai contra o mantra "comprometer-se cedo e comprometer-se com frequência", como no seu repositório, enquanto você está desenvolvendo, ainda tem detalhes granulares, portanto, você tem poucas chances de perder o trabalho e outras pessoas podem revisar / puxar / propor pr contra seu trabalho enquanto o novo pr está sendo desenvolvido.
fonte
A principal razão do que eu posso ver é a seguinte:
Merge pull request #123 from joebloggs/fix-snafoo
--first-parent
ponto de vista--first-parent
ponto de vista (observe que isso foi corrigido apenas no Git 2.6.2, para que pudéssemos perdoar o GitHub por não ter isso. acessível)Portanto, quando você combina todas as três situações acima, você obtém uma situação em que as confirmações não ordenadas que estão sendo mescladas parecem feias na interface do usuário do GitHub.
Seu histórico com confirmações esmagadas será algo como
Considerando que, sem commits esmagados, a história parecerá algo como
Quando você tem muitos commits em um rastreamento de relações públicas em que ocorreu uma mudança, pode se tornar um pesadelo se você se restringir ao uso da interface do usuário do GitHub .
Por exemplo, você encontra um ponteiro nulo sendo des-referenciado em algum lugar de um arquivo ... então você diz "quem fez isso e quando? Que versões de lançamento são afetadas?". Em seguida, você passa pela visão de culpa na interface do usuário do GitHub e vê que a linha foi alterada em
789fdfffdf
... "mas espere um segundo, essa linha estava apenas tendo seu recuo alterado para se encaixar no restante do código", então agora você precisa navegar para o estado da árvore desse arquivo no commit pai e visitar novamente a página da culpa ... eventualmente você encontra o commit ... é um commit de 6 meses atrás ... "ah **** isso pode estar afetando os usuários por 6 meses" você diz ... ah mas espere, esse commit estava na verdade em uma solicitação pull e só foi mesclada ontem e ninguém fez um lançamento ainda ... "Porra, gente por fundir commits sem esmagar o histórico" é o clamor que geralmente pode ser ouvido após cerca de 2 ou 3 expedições de arqueologia de código via UI do GitHubAgora, vamos considerar como isso funciona se você usar a linha de comando Git (e o incrível 2.6.2, que tem a correção
git blame --first-parent
)Portanto, nosso histórico de submissões se pareceria
Mas também podemos fazer
(Em outras palavras: a CLI do Git permite que você coma e coma também)
Agora, quando atingimos o problema do ponteiro nulo ... bem, apenas usamos
git blame --first-parent -w dodgy-file.c
e recebemos imediatamente o commit exato em que a referência de ponteiro nulo foi introduzida no ramo mestre, ignorando alterações simples de espaço em branco.Obviamente, se você estiver fazendo mesclagens usando a interface do usuário do GitHub, isso
git log --first-parent
é realmente péssimo, graças ao GitHub forçando a primeira linha da mensagem de confirmação de mesclagem:Então, para resumir uma longa história:
A interface do usuário do GitHub (outubro de 2015) tem várias deficiências na maneira como mescla solicitações pull, como apresenta o histórico de confirmação e como atribui informações de culpa. A melhor maneira atual de solucionar esses defeitos na interface do usuário do GitHub é solicitar às pessoas que comprimam suas confirmações antes da mesclagem.
A CLI do Git não possui esses problemas e você pode escolher facilmente qual visualização deseja ver para descobrir o motivo pelo qual uma alteração específica foi feita dessa maneira (olhando o histórico dos commits sem interrupção), bem como veja os commits efetivamente esmagados.
Post Script
A razão final frequentemente citada para comprimir commits é facilitar o backporting ... se você tiver apenas um commit para back port (ou seja, o commit squashed), será fácil escolher facilmente ...
Bem, se você está olhando para a história do git
git log --first-parent
, pode escolher os commits de mesclagem. A maioria das pessoas se confunde com confirmações de mesclagem de seleção de cereja porque você precisa especificar a-m N
opção, mas se você recebeu a confirmação a partir degit log --first-parent
então você sabe que é o primeiro pai que deseja seguir, assim serágit cherry-pick -m 1 ...
fonte
--first-parent
mim mesmo, a fim de ganhar um argumento contra commits esmagando ;-)Eu concordo com os sentimentos expressos em outras respostas neste tópico sobre mostrar um histórico claro e conciso dos recursos adicionados e dos bugs corrigidos. No entanto, gostaria de abordar outro aspecto que sua pergunta evitou, mas não declarou explicitamente. Parte do problema que você pode ter sobre alguns dos métodos de trabalho do git é que o git permite reescrever a história que parece estranha ao ser apresentada ao git após o uso de outras formas de controle de origem, onde tais ações são impossíveis. Além disso, isso também contraria o princípio geralmente aceito de controle de origem de que, quando algo for confirmado / verificado no controle de origem, você poderá reverter para esse estado, independentemente das alterações feitas após a confirmação. Como você sugere na sua pergunta, essa é uma dessas situações. Eu acho que o git é um ótimo sistema de controle de versão; no entanto, para entendê-lo, é necessário entender alguns dos detalhes de implementação e decisões de design subjacentes e, como resultado, possui uma curva de aprendizado mais acentuada. Lembre-se de que o git foi planejado para ser um sistema de controle de versão distribuído e isso ajudará a explicar por que os designers permitem que o histórico do git seja reescrito com o squash commits sendo um exemplo disso.
fonte
git gc
tenha sido executado para descartar objetos não referenciados.Por causa da perspectiva ... A melhor prática é ter um único commit por
<<issue-management-system>>
problema, se possível.Você pode ter quantos commits quiser em seu próprio ramo / repo, mas é seu histórico relevante para o que você está fazendo agora para a SUA perspectiva ... não é a HISTÓRIA para toda a EQUIPE / PROJETO ou aplicativo de seu perspectiva a ser mantida daqui a vários meses ...
Portanto, sempre que você desejar confirmar uma correção ou recurso de bug em um repositório comum (este exemplo é com o ramo de desenvolvimento), faça o seguinte:
como refazer sua ramificação de recursos para desenvolver rapidamente
fonte
Gostaria de ver se o código está sendo público ou não.
Quando os projetos permanecem privados:
Eu recomendaria não esmagar e ver a confecção da lingüiça. Se você usa confirmações boas e pequenas, ferramentas como o git bisect são super úteis e as pessoas podem identificar rapidamente as confirmações de regressão e ver por que você fez isso (por causa da mensagem de confirmação).
Quando os projetos se tornam públicos:
Esmague tudo porque alguns commits podem conter vazamentos de segurança. Por exemplo, uma senha que foi confirmada e removida novamente.
fonte