ref^
refere-se ao commit antes ref
, que tal obter o commit depois ref
?
Por exemplo, se eu, git checkout 12345
como verifico o próximo commit?
Obrigado.
PS Sim, o git é uma árvore de estrutura de ponteiro de nó do DAG. Como encontro o commit após este?
git
version-control
Schwern
fonte
fonte
git children-of
"!Respostas:
Para listar todos os commits, começando pelo atual e depois seu filho, e assim por diante - basicamente o log git padrão, mas seguindo o caminho inverso no tempo, use algo como
onde 894e8b4e93d8f3 é o primeiro commit que você deseja mostrar.
fonte
HEAD^
por894e8b4e93d8f3^
....
,^..
falha silenciosamentefatal: unrecognized argument: --ancestry-path
em git versão 1.7.1master
estiver no caminho de ascendência do commit atual. Veja o segundo trecho de código da minha resposta para obter uma solução que funcione em todos os casos.O criador do Hudson (agora Jenkins) Kohsuke Kawaguchi acaba de publicar (novembro de 2013):
kohsuke / git-children-of :
Como ilustrado por esta discussão , em um VCS baseado na história representada por um DAG (Directed Acyclic Graph) , não há "um pai" ou "um filho".
A ordenação das confirmações é feita por "ordem superior" ou "ordem da data" (consulte o livro GitPro )
Mas desde o Git1.6.0 , você pode listar os filhos de um commit.
Nota: para confirmações pai , você tem o mesmo problema, com o sufixo
^
de um parâmetro de revisão que significa o primeiro pai desse objeto de confirmação.^<n>
significa o<n>
th pai (ou seja,rev^
é equivalente arev^1
).Se você estiver no ramo
foo
e emitir "git merge bar
",foo
será o primeiro pai.Ou seja: o primeiro pai é o ramo em que você estava quando você mesclou e o segundo é o commit no ramo em que você mesclou.
fonte
git rev-list --children
certeza parece com o que eu quero, mas não DWIM. Parece listar todos os pais e filhos. Suponho que posso listá-los todos e analisá-los ... bleh, mas é alguma coisa.git rev-list --children
não é para listar apenas filhos, mas para listar pais e filhos ... você sempre precisa analisar.$ git children0of 9dd5932
fatal: No annotated tags can describe '71d7b5dd89d241072a0a078ff2c7dfec05d52e1f'.
However, there were unannotated tags: try --tags.
Qual saída você obtém?git-children-of
é que ele usa o git descrevem que tenta formatar o SHA como legível por humanos, o que pode falhar com o erro do @ TomHale e fornece resultados assimv1.0.4-14-g2414721
confusos se você esperava um SHA. Substituí-lo por um simplesecho
faz desta uma excelente ferramenta, obrigado!o que eu achei é
onde eu defini
commit1
como o commit atual ecommit2
para o head atual. Isso me retorna uma lista de todos os commits que constroem um caminho entrecommit1
ecommit2
.A última linha da saída é filha de commit1 (no caminho para commit2).
fonte
| tail -1
para pegar a criança.Eu sei o que você quer dizer. É frustrante ter uma sintaxe abundante para ir para confirmações anteriores, mas nenhuma para ir para as próximas. Em uma história complexa, o problema de "qual é o próximo commit" torna-se bastante difícil, mas depois, na mesclagem complexa, a mesma dureza surge com os commits 'anteriores'. No caso simples, dentro de um único ramo com um histórico linear (mesmo localmente para um número limitado de confirmações), seria bom e faria sentido avançar e retroceder.
O problema real com isso, no entanto, é que os filhos confirmados não são referenciados, é apenas uma lista vinculada ao contrário. Encontrar o commit filho requer uma pesquisa, o que não é muito ruim, mas provavelmente não é algo que o git deseja colocar na lógica refspec.
De qualquer forma, me deparei com essa pergunta porque simplesmente quero avançar na história que um commit de cada vez, fazendo testes, e às vezes você precisa dar um passo à frente e não para trás. Bem, pensando um pouco mais, eu vim com esta solução:
Escolha um commit antes de onde você está. Provavelmente poderia ser uma cabeça de ramo. Se você estiver no ramo ~ 10, "git checkout branch ~ 9" e "git checkout branch ~ 8" para obter o próximo depois disso, "git checkout branch ~ 7" e assim por diante.
Diminuir o número deve ser realmente fácil em um script, se você precisar. Muito mais fácil do que analisar git rev-list.
fonte
BRANCH=master; git co $BRANCH~$[ $(git rev-list HEAD..$BRANCH | wc -l) - 1 ]
" Você tem que ir em direção a um galho, de jeito nenhum.Duas respostas práticas:
Uma criança
Com base na resposta de @ Michael , cortei o
child
alias no meu.gitconfig
.Funciona como esperado no caso padrão e também é versátil.
O padrão é fornecer o filho de HEAD (a menos que outro argumento de confirmação seja fornecido) seguindo a ancestralidade um passo em direção à ponta do ramo atual (a menos que outro commit-ish seja fornecido como segundo argumento).
Use em
%h
vez de%H
se desejar o formato de hash curto.Vários filhos
Com um HEAD desanexado (não há ramo) ou para obter todos os filhos, independentemente dos ramos:
Mude
$1
para$*
para imprimir todos os filhos.Você também pode mudar
--all
para um commit-ish para exibir apenas os filhos que são ancestrais desse commit - em outras palavras, para exibir apenas os filhos “na direção” do commit fornecido. Isso pode ajudá-lo a reduzir a produção de muitos filhos para apenas um.fonte
Não existe um "próximo commit" exclusivo. Como o histórico no Git é um DAG, e não uma linha, muitos commits podem ter um pai comum (ramificações) e os commits podem ter mais de um pai (mesclagens).
Se você tem uma ramificação específica em mente, pode ver o log e ver qual confirmação lista a atual como pai.
fonte
<rev>^
é "pai confirmado" ('primeiro pai' para confirmações de mesclagem).Eu tentei muitas soluções diferentes e nenhuma funcionou para mim. Tinha que inventar o meu.
encontre o próximo commit
encontre confirmação anterior
fonte
No caso em que você não tem uma confirmação de "destino" específica em mente, mas deseja ver confirmações filho que possam estar em qualquer ramificação, você pode usar este comando:
Se você quiser ver todos os filhos e netos , precisará usar
rev-list --children
recursivamente, assim:(A versão que fornece apenas netos usaria um conjunto mais complexo
sed
e / oucut
.)Finalmente, você pode alimentar isso em um
log --graph
comando para ver a estrutura da árvore, assim:Nota : todos os comandos acima assumem que você configurou a variável shell
${COMMIT}
para alguma referência (branch, tag, sha1) do commit em cujos filhos você está interessado.fonte
${COMMIT}
does not ESIST, mas você poderia usar$(git rev-parse HEAD)
em vez${COMMIT}
.(Isso começou como uma resposta a uma pergunta duplicada. Fiz um pouco de edição leve para limpá-la.)
Todas as setas internas do Git são unidirecionais, apontando para trás. Portanto, não existe uma sintaxe curta e conveniente para avançar: simplesmente não é possível.
Ele é possível "movimento contra as flechas", mas a maneira de fazer isso é surpreendente, se você não tê-lo visto antes, e depois óbvio depois. Digamos que temos:
O uso
middle~2
segue as setas duas vezes deC
volta paraA
. Então, como passamosC
paraD
? A resposta é: começamosE
usando o nomelast
e trabalhamos para trás até chegarmosmiddle
, registrando os pontos que visitamos ao longo do caminho . Depois, apenas avançamos o quanto queremos na direção delast
: mova um passo paraD
, ou dois paraE
.Isso é particularmente importante quando temos filiais:
Qual commit é um passo depois
C
? Não há resposta correta até você adicionar à pergunta: na direção do recurso___ (preencha o espaço em branco).Para enumerar os commits entre
C
(excluindoC
) em si e, digamos,G
usamos:Os
--topo-order
garante que, mesmo na presença do complexo ramificação-and-fusão, os commits sair, a fim topologicamente-ordenada. Isso é necessário apenas se a corrente não for linear. A--ancestry-path
restrição significa que, quando trabalhamos de trás para frentefeature2
, listamos apenas confirmações que foram confirmadasC
como um de seus ancestrais. Ou seja, se o gráfico - ou a parte relevante dele de qualquer maneira - se parecer com isso:um simples pedido do formulário
feature2..master
enumera commitsJ
,G
eI
, eF
eH
em alguma ordem. Com--ancestry-path
nós nocauteamosH
eI
: eles não são descendentes deC
, apenas deA
. Com--topo-order
, garantimos que a ordem de enumeração real sejaJ
, entãoG
, entãoF
.O
git rev-list
comando espalha esses IDs de hash em sua saída padrão, um por linha. Para avançar um passo na direção defeature2
, então, queremos apenas a última linha.É possível (e tentador e pode ser útil) adicionar
--reverse
para quegit rev-list
imprima os commits em ordem inversa após gerá-los. Isso funciona, mas se você o usar em um pipeline como este:para obter o "próximo commit na direção do id2", e há uma lista muito longa de commits, o
git rev-list
comando pode obter um pipe quebrado ao tentar gravar nohead
qual parou de ler sua entrada e saiu. Como erros de tubos quebrados são normalmente ignorados pelo shell, isso geralmente funciona. Apenas verifique se eles são ignorados no seu uso.Também é tentador adicionar
-n 1
aogit rev-list
comando, juntamente com--reverse
. Não faça isso! Isso faz com que vocêgit rev-list
pare depois de dar um passo para trás e inverta a lista de confirmações visitadas (uma entrada). Então, isso só produz<id2>
sempre.Nota lateral importante
Observe que com os fragmentos do gráfico "diamante" ou "anel benzeno":
movendo um commit "forward" de
H
direçãolast
vai te querI
ouK
. Não há nada que você possa fazer sobre isso: ambos os commits estão um passo à frente! Se você iniciar a partir do commit resultante e seguir outra etapa, agora estará comprometido com o caminho que iniciou.A cura para isso é evitar dar um passo de cada vez e ficar preso a cadeias dependentes do caminho. Em vez disso, se você planeja visitar uma cadeia inteira de caminho de ancestralidade, antes de fazer qualquer outra coisa , faça uma lista completa de todos os commits na cadeia:
Em seguida, visite cada confirmação nesta lista, uma de cada vez, e você obterá toda a cadeia. O
--topo-order
fará com que você bateuI
-e-J
nessa ordem, eK
e-L
nessa ordem (embora não há nenhuma maneira fácil de prever se você vai fazer o par IJ antes ou depois de o par KL).fonte
Eu tenho esse apelido em
~/.gitconfig
fonte
f()
? E precisahead -1
ser o primeiro filho, caso contrário, isso simplesmente informará o HEAD.f()
. Sim,head -1
é um palpite corajoso.nextref = "!f() { git log --reverse --ancestry-path --pretty=%H $1..HEAD | head -${2:-1} | tail -1; }; f"
assim que você pode escolher como muito à frente, opcionalmenteConsegui encontrar o próximo filho da seguinte maneira:
fonte
Se as confirmações filho estiverem todas em alguma ramificação, você poderá usar
gitk --all commit^..
, onde "confirmar" é algo que identifica a confirmação. Por exemplo, se o SHA-1 abreviado da confirmação for c6661c5, digitegitk --all c6661c5^..
Você provavelmente precisará inserir o SHA-1 completo na célula "SHA1 ID:" do gitk. Você precisará do SHA-1 completo, que para este exemplo pode ser obtido via
git rev-parse c6661c5
Como alternativa,
git rev-list --all --children | grep '^c6661c5883bb53d400ce160a5897610ecedbdc9d'
produzirá uma linha contendo todos os filhos desse commit, presumivelmente se existe ou não um ramo envolvido.fonte
Cada confirmação armazena um ponteiro para o pai (pais, em caso de consolidação (padrão)).
Portanto, não há como apontar para um commit filho (se houver) do pai.
fonte
Esta publicação ( http://www.jayway.com/2015/03/30/using-git-commits-to-drive-a-live-coding-session/#comment-282667 ) mostra uma maneira elegante de fazê-lo, se você pode criar uma tag bem definida no final da sua pilha de confirmação. Essencialmente,
git config --global alias.next '!git checkout `git rev-list HEAD..demo-end | tail -1`'
onde "demo-end" é a última tag.fonte
As respostas existentes assumem que você tem um ramo que contém o commit que você está procurando.
No meu caso, o commit que eu estava procurando não estava,
git rev-list --all
pois nenhum ramo continha isso.Acabei olhando
gitk --reflog
manualmente.Se você não conseguir encontrar seu commit nem no reflog, tente:
git fsck --full
para listar confirmações pendentes (ou seja, que não estejam em nenhum ramo)git fsck --lost-found
fazer refs apontando para dangling se compromete a aplicar técnicas nas outras respostas.fonte