Imagine a seguinte história:
c---e---g--- feature
/ \
-a---b---d---f---h--- master
Como posso descobrir quando a consolidação "c" foi mesclada no mestre (ou seja, encontrar a consolidação de mesclagem "h")?
Imagine a seguinte história:
c---e---g--- feature
/ \
-a---b---d---f---h--- master
Como posso descobrir quando a consolidação "c" foi mesclada no mestre (ou seja, encontrar a consolidação de mesclagem "h")?
Respostas:
Seu exemplo mostra que a ramificação feature ainda está disponível.
Nesse caso, hé o último resultado de:
git log master ^feature --ancestry-path
Se a ramificação featurenão estiver mais disponível, você poderá mostrar os commits de mesclagem na linha do histórico entre ce master:
git log <SHA-1_for_c>..master --ancestry-path --merges
No entanto, isso também mostrará todas as mesclagens que ocorreram depois he entre ee gdepois feature.
Comparando o resultado dos seguintes comandos:
git rev-list <SHA-1_for_c>..master --ancestry-path
git rev-list <SHA-1_for_c>..master --first-parent
fornecerá o SHA-1 hcomo a última linha em comum.
Se você o tiver disponível, poderá usar comm -1 -2esses resultados. Se você estiver no msysgit, poderá usar o seguinte código perl para comparar:
perl -ne 'print if ($seen{$_} .= @ARGV) =~ /10$/' file1 file2
(código perl de http://www.cyberciti.biz/faq/command-to-display-lines-common-in-files/ , que retirou de "alguém do grupo de notícias comp.unix.shell").
Consulte a substituição do processo se você deseja torná-lo uma linha.
mastersido mesclado e feature, imediatamente, featuremesclado mastercomo um avanço rápido (dica de featuresubstituições master). Isso causaria o --first-parentretorno do pai errado?
comm -1 -2mas não funcionou. commsó funciona em linhas classificadas. (O perl one-liner funciona, embora eu não poderia lê-lo.)
git find-merge h master(não retorna nada, mas deve retornar h), git find-merge d master(retorna f, mas deve retornar d), git find-merge c feature(retorna e, mas deve retornar g).
Adicione isto ao seu ~/.gitconfig:
[alias]
find-merge = "!sh -c 'commit=$0 && branch=${1:-HEAD} && (git rev-list $commit..$branch --ancestry-path | cat -n; git rev-list $commit..$branch --first-parent | cat -n) | sort -k2 -s | uniq -f1 -d | sort -n | tail -1 | cut -f2'"
show-merge = "!sh -c 'merge=$(git find-merge $0 $1) && [ -n \"$merge\" ] && git show $merge'"
Então você pode usar os aliases como este:
# current branch
git find-merge <SHA-1>
# specify master
git find-merge <SHA-1> master
Para ver a mensagem do commit de mesclagem e outros detalhes, use git show-mergecom os mesmos argumentos.
(Com base na resposta de Gauthier . Agradecemos a Rosen Matev e javabrett por corrigir um problema sort.)
sort -k2 | uniq -f1 -d | sort -n | tail -1 | cut -f2não encontrar corretamente a última linha em comum. Aqui está um exemplo em que falha.
16db9fef5c581ab0c56137d04ef08ef1bf82b0b7aqui quando eu o executo na sua pasta, isso não é esperado? Em qual SO você está?
29c40c3a3b33196d4e79793bd8e503a03753bad1
O git-get-merge irá localizar e mostrar o commit de mesclagem que você está procurando:
pip install git-get-merge
git get-merge <SHA-1>
O comando segue os filhos do commit fornecido até que uma mesclagem em outro ramo (presumivelmente mestre) seja encontrada.
Ou seja, para resumir o post de Gauthier:
perl -ne 'print if ($seen{$_} .= @ARGV) =~ /10$/' <(git rev-list --ancestry-path <SHA-1_for_c>..master) <(git rev-list --first-parent <SHA-1_for_c>..master) | tail -n 1
EDIT: porque usa substituição de processo " <()", não é compatível com POSIX, e pode não funcionar com seu shell. Funciona com bashou zshembora.
<()não é compatível com POSIX. Você precisa usar bash, zshou uma concha apoiar substituição processo . Eu editei minha resposta de acordo.
Eu precisava fazer isso e, de alguma forma, encontrei git-when-merged(o que realmente faz referência a essa pergunta do SO, mas Michael Haggerty nunca adicionou uma referência ao seu muito bom script Python aqui). Então agora eu tenho.
Com base na grande resposta de Gauthier, não precisamos usar commpara comparar as listas. Como estamos procurando o último resultado no --ancestry-pathqual também está --first-parent, podemos simplesmente saudar o último na saída do primeiro:
git rev-list <SHA>..master --ancestry-path | grep -f <(git rev-list <SHA>..master --first-parent) | tail -1
Ou, para algo rápido e reutilizável, aqui está uma função para aparecer .bashrc:
function git-find-merge() {
git rev-list $1..master --ancestry-path | grep -f <(git rev-list $1..master --first-parent) | tail -1
}
commnão funcionou quando as entradas não foram classificadas.
Para a multidão de Ruby, há coisas sem sentido . Muito fácil.
$ gem install git-whence
$ git whence 1234567
234557 Merge pull request #203 from branch/pathway
Eu uso o script bash abaixo, que coloco no caminho ~/bin/git-find-merge. É baseado na resposta de Gauthier e na resposta do evilstreak com poucos ajustes para lidar com casos de canto. commlança quando as entradas não são classificadas. grep -ffunciona perfeitamente.
Caixas de canto:
~/bin/git-find-merge roteiro:
#!/bin/bash
commit=$1
if [ -z $commit ]; then
echo 1>&2 "fatal: commit is required"
exit 1
fi
commit=$(git rev-parse $commit)
branch=${2-@}
# if branch points to commit (both are same), then return commit
if [ $commit == $(git rev-parse $branch) ]; then
git log -1 $commit
exit
fi
# if commit is a merge commit on first-parent path of branch,
# then return commit
# if commit is a NON-merge commit on first-parent path of branch,
# then return branch as it's either a ff merge or commit is only on branch
# and there is not a good way to figure out the right commit
if [[ $(git log --first-parent --pretty='%P' $commit..$branch | \
cut -d' ' -f1 | \
grep $commit | wc -l) -eq 1 ]]; then
if [ $(git show -s --format="%P" $commit | wc -w) -gt 1 ]; then
# if commit is a merge commit
git log -1 $commit
else
# if commit is a NON-merge commit
echo 1>&2 ""
echo 1>&2 "error: returning the branch commit (ff merge or commit only on branch)"
echo 1>&2 ""
git log -1 $branch
fi
exit
fi
# 1st common commit from bottom of first-parent and ancestry-path
merge=$(grep -f \
<(git rev-list --first-parent $commit..$branch) \
<(git rev-list --ancestry-path $commit..$branch) \
| tail -1)
if [ ! -z $merge ]; then
git log -1 $merge
exit
fi
# merge commit not found
echo 1>&2 "fatal: no merge commit found"
exit 1
O que me permite fazer isso:
(master)
$ git find-merge <commit> # to find when commit merged to current branch
$ git find-merge <branch> # to find when branch merged to current branch
$ git find-merge <commit> pu # to find when commit merged to pu branch
Este script também está disponível no meu github .
Minha versão ruby da idéia do @ robinst, funciona duas vezes mais rápido (o que é importante ao procurar por commit muito antigo).
find-commit.rb
commit = ARGV[0]
master = ARGV[1] || 'origin/master'
unless commit
puts "Usage: find-commit.rb commit [master-branch]"
puts "Will show commit that merged <commit> into <master-branch>"
exit 1
end
parents = `git rev-list #{commit}..#{master} --reverse --first-parent --merges`.split("\n")
ancestry = `git rev-list #{commit}..#{master} --reverse --ancestry-path --merges`.split("\n")
merge = (parents & ancestry)[0]
if merge
system "git show #{merge}"
else
puts "#{master} doesn't include #{commit}"
exit 2
end
Você pode usá-lo assim:
ruby find-commit.rb SHA master
Você pode tentar algo assim. A idéia é percorrer todos os commit de mesclagem e ver se o commit "c" é acessível a partir de um deles:
$ git log --merges --format='%h' master | while read mergecommit; do
if git log --format='%h' $mergecommit|grep -q $c; then
echo $mergecommit;
break
fi
done
git rev-list <SHA-1_for_c>..master --ancestry-path --merges
Eu tive que fazer isso várias vezes (obrigado a todos que responderam a essa pergunta!) E acabei escrevendo um script (usando o método de Gauthier) que eu poderia adicionar à minha pequena coleção de utilitários git. Você pode encontrá-lo aqui: https://github.com/mwoehlke/git-utils/blob/master/bin/git-merge-point .