मर्ज कमिटमेंट खोजें जिसमें एक विशिष्ट कमिट शामिल हो


183

निम्नलिखित इतिहास की कल्पना करें:

       c---e---g--- feature
      /         \
-a---b---d---f---h--- master

मैं कैसे पा सकता हूं जब "सी" को मास्टर में विलय कर दिया गया है (यानी, मर्ज कमिट "एच" खोजें)?

जवाबों:


158

आपका उदाहरण दिखाता है कि शाखा featureअभी भी उपलब्ध है।

उस मामले hमें अंतिम परिणाम है:

git log master ^feature --ancestry-path

शाखा तो featureअब उपलब्ध नहीं है, तो आप के बीच इतिहास लाइन में मर्ज करता दिखा सकते हैं cऔर master:

git log <SHA-1_for_c>..master --ancestry-path --merges

हालांकि यह भी सभी का आपस में विलय के बाद हुआ दिखाई देगा h, और के बीच eऔर gपर feature


निम्नलिखित आदेशों के परिणाम की तुलना:

git rev-list <SHA-1_for_c>..master --ancestry-path

git rev-list <SHA-1_for_c>..master --first-parent

आपको hअंतिम पंक्ति के रूप में SHA-1 देगा ।

यदि आपके पास यह उपलब्ध है, तो आप comm -1 -2इन परिणामों पर उपयोग कर सकते हैं । यदि आप msysgit पर हैं, तो आप तुलना करने के लिए निम्न पर्ल कोड का उपयोग कर सकते हैं:

perl -ne 'print if ($seen{$_} .= @ARGV) =~ /10$/'  file1 file2

(से पर्ल कोड http://www.cyberciti.biz/faq/command-to-display-lines-common-in-files/ है, जो "comp.unix.shell समाचार समूह में किसी को" से ले लिया)।

यदि आप इसे एक-लाइनर बनाना चाहते हैं, तो प्रक्रिया प्रतिस्थापन देखें ।


4
यहां तक ​​कि अगर आप आते हैं, तो आप इसका उपयोग नहीं कर सकते क्योंकि "git Rev-list" कमांड का आउटपुट lexicographically सॉर्ट नहीं किया गया है। आप आम पंक्तियों की तलाश करने से पहले प्रत्येक कमांड के आउटपुट को क्रमबद्ध कर सकते हैं, लेकिन तब वांछित कमिट अंतिम रूप से नहीं होगा। इसलिए मुझे लगता है कि पर्ल कमांड (हालांकि अस्पष्ट) जैसा कुछ आवश्यक है।
महागर

12
मैंने सिर्फ एक स्क्रिप्ट गिट-जब-मर्ज लिखा था जो इस सुझाव को लागू करता है (कुछ अन्य विशेषताओं के साथ)। देखें github.com/mhagger/git-when-merged
mhagger

2
कुछ बिंदु पर मान लीजिए masterमें विलय हो गया feature, तो तुरंत featureमें विलय कर दिया गया है masterतेजी से आगे (की नोक के रूप में featureकी जगह master)। क्या वह --first-parentगलत माता-पिता को वापस करने का कारण होगा ?
केल्विन

4
मैंने कोशिश की comm -1 -2लेकिन यह काम नहीं किया। commकेवल हल की गई लाइनों पर काम करता है। (पर्ल वन-लाइनर काम करता है, हालांकि मैं इसे नहीं पढ़ सका।)
डोमन

2
यह थोड़ा देर से है, लेकिन लोगों को जोड़ने से यह उपयोगी हो सकता है क्योंकि यह देशी रूप से प्रदान नहीं करता है। कुछ कोने के मामले हैं जो मुझे लगता है कि यह उत्तर संभाल नहीं करता है (मेरे जवाब के नीचे देखें stackoverflow.com/a/43716029/58678 जो अधिकांश कोने के मामलों को संभालता है)। यहां कोने के मामले हैं: git find-merge h master(कुछ भी नहीं है लेकिन एच वापस लौटना चाहिए), git find-merge d master(रिटर्न एफ लेकिन डी वापस लौटना चाहिए), git find-merge c feature(रिटर्न ई लेकिन जी लौटना चाहिए)।
hppy

133

इसे अपने में जोड़ें ~/.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'"

तो आप इस तरह उपनाम का उपयोग कर सकते हैं:

# current branch
git find-merge <SHA-1>
# specify master
git find-merge <SHA-1> master

मर्ज कमिट के संदेश और अन्य विवरण देखने के लिए, का उपयोग करें git show-merge उसी तर्कों के साथ ।

( गौथियर के जवाब पर आधारित । रोसेन माटेव और धन्यवाद के साथ एक समस्या को ठीक करने के लिए javabrettsort ।)


6
सुंदर! यह सबसे अच्छा ड्रॉप-इन समाधान है।
एन जोन्स

1
खबरदार जो sort -k2 | uniq -f1 -d | sort -n | tail -1 | cut -f2सामान्य रूप से अंतिम पंक्ति को सही ढंग से नहीं ढूंढ रहा है। यहाँ एक उदाहरण है जहाँ यह विफल रहता है।
रोटे मातेव

1
@RosenMatev 16db9fef5c581ab0c56137d04ef08ef1bf82b0b7जब मैं इसे आपके पेस्ट पर चलाता हूं, तो यह पता चलता है कि क्या यह अपेक्षित नहीं है? आप किस ओएस पर हैं?
23

1
@robinst, तुम्हारा सही है। मुझे "(GNU कोरुटिल्स) 8.4 मिला है" और मेरे लिए यह पाता है29c40c3a3b33196d4e79793bd8e503a03753bad1
रोसेन माटेव

2
@ पोलो: कुछ नहीं, सुविधा के लिए यह दो के बजाय सिर्फ एक कमांड है।
रॉबिन

28

गिट-गेट-मर्ज का पता लगाएगा और उस मर्ज कमिट को दिखाएगा, जिसकी आप तलाश कर रहे हैं:

pip install git-get-merge
git get-merge <SHA-1>

कमांड दिए गए कमिट के बच्चों का अनुसरण तब तक करता है जब तक कि दूसरी ब्रांच में विलय (संभवतः मास्टर) नहीं मिल जाता।


22

गौथियर के पद को संक्षेप में प्रस्तुत करना है:

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: क्योंकि यह प्रक्रिया प्रतिस्थापन " <()" का उपयोग करता है , यह POSIX संगत नहीं है, और यह आपके शेल के साथ काम नहीं कर सकता है। यह साथ bashया zshयद्यपि काम करता है ।


4
मैं अक्सर इंटरनेट से कोड कॉपी / पेस्ट नहीं करता, लेकिन जब मैं करता हूं तो यह पूरी तरह से काम करता है! मुझे सोचने की अनुमति नहीं देने के लिए धन्यवाद टोटर।
बेन

2
@ TheodoreR.Smith दुर्भाग्य से, वाक्यविन्यास <()POSIX संगत नहीं है। आपको उपयोग करने की आवश्यकता है bash, zshया शेल सपोर्टिंग प्रोसेस प्रतिस्थापन है । मैंने उसी के अनुसार अपना उत्तर संपादित किया।
टॉटर

मेरे लिए काम नहीं किया। मुझे लगता है कि मेरी सुविधा शाखा पहली बार किसी अन्य शाखा में विलय हो गई, इससे पहले कि वह मास्टर में विलय हो जाए। यह समझा सकता है कि आपके आदेशों का परिणाम "मर्ज शाखा '' फीचर_ब्रांच 'के बजाय" मर्ज शाखा' रिलीज़_ब्रांच '"है।
टिम कुइपर्स 13

14

मुझे ऐसा करने की ज़रूरत थी, और किसी तरह पाया गया git-when-merged(जो वास्तव में इस एसओ प्रश्न का संदर्भ देता है, लेकिन माइकल हाग्गर्टी ने कभी भी अपनी बहुत अच्छी पायथन स्क्रिप्ट का संदर्भ नहीं जोड़ा)। तो अब मेरे पास है।


मैं वास्तव में उनके पेज से इस सवाल पर आया था।
फ्लाविस

12

Gauthier के महान उत्तर पर बिल्डिंग, हमें commसूचियों की तुलना करने के लिए उपयोग करने की आवश्यकता नहीं है । चूंकि हम अंतिम परिणाम की तलाश कर रहे हैं, --ancestry-pathजिसमें --first-parentहम भी हैं , हम बस पूर्व के आउटपुट में बाद के लिए जीआरपी कर सकते हैं:

git rev-list <SHA>..master --ancestry-path | grep -f <(git rev-list <SHA>..master --first-parent) | tail -1

या कुछ दुखी और पुन: प्रयोज्य के लिए, यहाँ एक समारोह पॉप में है .bashrc:

function git-find-merge() {
  git rev-list $1..master --ancestry-path | grep -f <(git rev-list $1..master --first-parent) | tail -1
}

इसने मेरे लिए काम किया। commइनपुट्स सॉर्ट नहीं किए जाने पर काम नहीं किया।
hIpPy


4

मैं बैश स्क्रिप्ट का उपयोग करता हूं, जिसे मैं पथ पर रखता हूं ~/bin/git-find-merge। यह कोने के मामलों को संभालने के लिए कुछ ट्वीक्स के साथ गौथियर के जवाब और बैडस्ट्रेक के उत्तर पर आधारित है । commजब इनपुट सॉर्ट नहीं किए जाते हैं तो फेंकता है। grep -fअच्छी तरह से काम।

कोने के मामले:

  • यदि प्रतिबद्ध, शाखा के पहले-मूल पथ पर एक मर्ज कमिट है, तो कमिट करें।
  • यदि प्रतिबद्ध शाखा के पहले-मूल पथ पर एक गैर-मर्ज कमिट है, तो शाखा लौटें। यह या तो एक एफएफ मर्ज है या कमिटमेंट केवल शाखा पर है और सही प्रतिबद्ध का पता लगाने का एक अच्छा तरीका नहीं है।
  • अगर कमिट और ब्रांच एक ही हैं, तो कमिट करें।

~/bin/git-find-merge स्क्रिप्ट:

#!/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

जो मुझे यह करने देता है:

(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

यह लिपि मेरे गितुब पर भी उपलब्ध है ।


2
git log --topo-order

फिर कमिट से पहले पहला मर्ज देखें।


1

@ रॉबिन्सन के विचार का मेरा माणिक संस्करण, दो बार तेजी से काम करता है (जो बहुत पुरानी प्रतिबद्धताओं की खोज करते समय महत्वपूर्ण है)।

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

आप इसे इस तरह से उपयोग कर सकते हैं:

ruby find-commit.rb SHA master

0

आप कुछ इस तरह की कोशिश कर सकते हैं। यह विचार सभी मर्ज कमिट के माध्यम से पुनरावृति करना है और देखें कि क्या कमिट "सी" उनमें से किसी एक से उपलब्ध है:

$ 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
यूजेन कोनकोव

0

मुझे यह कई बार करना पड़ा (इस प्रश्न का उत्तर देने वाले सभी के लिए धन्यवाद!), और एक पटकथा लिखना (Gauthier’s method का उपयोग करके) जिसे मैं अपने छोटे से संग्रह में उपयोगिताओं में जोड़ सकता था। आप इसे यहाँ पा सकते हैं: https://github.com/mwoehlke/git-utils/blob/master/bin/git-merge-point

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.