पायथन लिपि में वर्तमान गिट हैश प्राप्त करें


165

मैं पायथन स्क्रिप्ट के आउटपुट में वर्तमान git हैश को शामिल करना चाहूंगा ( कोड के संस्करण संख्या के रूप में जो उस आउटपुट को उत्पन्न करता है)।

मैं अपनी पायथन लिपि में वर्तमान git हैश का उपयोग कैसे कर सकता हूं?


7
git rev-parse HEADकमांड लाइन से शुरू करें । आउटपुट सिंटैक्स स्पष्ट होना चाहिए।
मेल निकोलसन

जवाबों:


96

git describeआदेश कोड का मनुष्य द्वारा आकर्षक "संस्करण संख्या" बनाने का एक अच्छा तरीका है। प्रलेखन में उदाहरणों से:

Git.git के वर्तमान पेड़ की तरह कुछ के साथ, मुझे मिलता है:

[torvalds@g5 git]$ git describe parent
v1.0.4-14-g2414721

यानी मेरी "पैरेंट" शाखा का वर्तमान प्रमुख v1.0.4 पर आधारित है, लेकिन चूंकि इसमें कुछ कमियाँ हैं, इसलिए वर्णन में अतिरिक्त कमिट्स की संख्या ("14") और एक संक्षिप्त वस्तु का नाम शामिल है। अंत में खुद ("2414721")।

पायथन के भीतर से, आप निम्न की तरह कुछ कर सकते हैं:

import subprocess
label = subprocess.check_output(["git", "describe"]).strip()

3
इसका दोष यह है कि यदि कोड को कभी भी git repo के बिना चलाया जाता है तो संस्करण मुद्रण कोड टूट जाएगा। उदाहरण के लिए, उत्पादन में। :)
जोसेफसाद

5
@JosefAssad: यदि आपको उत्पादन में संस्करण पहचानकर्ता की आवश्यकता है, तो आपकी परिनियोजन प्रक्रिया उपरोक्त कोड को चलाना चाहिए और परिणाम उत्पादन के लिए तैनात कोड में "बेक किया हुआ" होना चाहिए।
ग्रेग हेविगिल

14
ध्यान दें कि अगर कोई टैग मौजूद नहीं है तो git वर्णन विफल हो जाएगा:fatal: No names found, cannot describe anything.
kynan

40
git describe --alwaysपिछले करने के लिए वापस आने जाएगा प्रतिबद्ध अगर कोई टैग पाए जाते हैं
लियोनार्डो

5
@CharlieParker: git describeआम तौर पर कम से कम एक टैग की आवश्यकता होती है। यदि आपके पास कोई टैग नहीं है, तो --alwaysविकल्प का उपयोग करें । देखें Git प्रलेखन का वर्णन अधिक जानकारी के लिए।
ग्रेग हेवगिल जूल

190

gitखुद कमांड से डेटा प्राप्त करने के लिए हैक करने की आवश्यकता नहीं है । GitPython यह करने के लिए एक बहुत अच्छा तरीका है और अन्य gitसामान। यहां तक ​​कि इसमें विंडोज के लिए "सर्वश्रेष्ठ प्रयास" समर्थन भी है।

के बाद pip install gitpythonआप कर सकते हैं

import git
repo = git.Repo(search_parent_directories=True)
sha = repo.head.object.hexsha

9
@ क्रिशोज निश्चित नहीं है कि जब आप ऐसा करते हैं तो आप इसे पोर्टेबल कैसे कह सकते हैं ImportError: No module named gitpython:। आप gitpythonस्थापित होने वाले अंतिम उपयोगकर्ता पर भरोसा नहीं कर सकते हैं , और उन्हें अपने कोड के काम करने से पहले इसे स्थापित करने की आवश्यकता होती है जो इसे पोर्टेबल नहीं बनाता है। जब तक आप स्वचालित इंस्टॉलेशन प्रोटोकॉल को शामिल नहीं करने जा रहे हैं, तब तक यह एक स्वच्छ समाधान नहीं है।
user5359531

39
@ user5359531 मैं अलग से भीख माँगता हूँ। GitPython एक शुद्ध पायथन कार्यान्वयन प्रदान करता है, जो प्लेटफ़ॉर्म-विशिष्ट विवरणों को अलग करता है, और यह सभी प्लेटफ़ॉर्म पर मानक पैकेज टूल ( pip/ requirements.txt) का उपयोग करके इंस्टॉल करने योग्य होता है। "साफ" क्या नहीं है?
क्रिशोज

22
यह पायथन में चीजों को करने का सामान्य तरीका है। यदि ओपी को उन आवश्यकताओं की आवश्यकता होती है, तो उन्होंने ऐसा कहा होगा। हम मन-पाठक नहीं हैं, हम प्रत्येक प्रश्न में प्रत्येक घटना की भविष्यवाणी नहीं कर सकते हैं। वह रास्ता पागलपन है।
OldTinfoil

14
@ user5359531, मैं स्पष्ट नहीं हूँ कि स्टैकओवरफ़्लो import numpy as npके पूरे क्षेत्र में क्यों ग्रहण किया जा सकता है लेकिन gitpython स्थापित करना 'स्वच्छ' और 'पोर्टेबल' से परे है। मुझे लगता है कि यह अब तक का सबसे अच्छा समाधान है, क्योंकि यह पहिया को सुदृढ़ नहीं करता है, बदसूरत कार्यान्वयन को दूर करता है और उपप्रकार से गिट के जवाब को हैक करने के आसपास नहीं जाता है।
जाब्लास्को

7
@ user5359531 जबकि मैं सामान्य रूप से सहमत हूं कि आपको हर छोटी समस्या पर एक चमकदार नई लाइब्रेरी नहीं फेंकनी चाहिए, "पोर्टेबिलिटी" की आपकी परिभाषा आधुनिक परिदृश्यों को नजरअंदाज करती है, जहां डेवलपर्स का सभी वातावरणों पर पूर्ण नियंत्रण है। डॉकटर कंटेनर, आभासी वातावरण और मशीन की छवियां (जैसे एएमआई) pipया आसानी से स्थापित करने की क्षमता pip। इन आधुनिक परिदृश्यों में, एक pipसमाधान "मानक पुस्तकालय" समाधान के रूप में पोर्टेबल है।
रयान

106

इस पोस्ट में कमांड है, ग्रेग के जवाब में सबप्रोसेस कमांड है।

import subprocess

def get_git_revision_hash():
    return subprocess.check_output(['git', 'rev-parse', 'HEAD'])

def get_git_revision_short_hash():
    return subprocess.check_output(['git', 'rev-parse', '--short', 'HEAD'])

32
परिणाम को बिना लाइन ब्रेक के प्राप्त करने के लिए एक स्ट्रिप () जोड़ें :)
टिड्डा

आप एक विशेष पथ पर git रेपो के लिए इसे कैसे चलाएंगे?
1

2
@pkamb का उपयोग करें। gd रेपो के पथ पर सीडी के लिए। आप के साथ काम करने में रुचि रखते हैं
Zac Crites

यदि वर्तमान में चेक किया गया संशोधन शाखा प्रमुख नहीं है तो क्या वह गलत जवाब नहीं देगा?
अधिकतम

7
.decode('ascii').strip()बाइनरी स्ट्रिंग को डीकोड करने के लिए एक जोड़ें (और लाइन ब्रेक को हटा दें)।
pfm

13

numpyएक अच्छी दिखने वाली बहु-मंच दिनचर्या है setup.py:

import os
import subprocess

# Return the git revision as a string
def git_version():
    def _minimal_ext_cmd(cmd):
        # construct minimal environment
        env = {}
        for k in ['SYSTEMROOT', 'PATH']:
            v = os.environ.get(k)
            if v is not None:
                env[k] = v
        # LANGUAGE is used on win32
        env['LANGUAGE'] = 'C'
        env['LANG'] = 'C'
        env['LC_ALL'] = 'C'
        out = subprocess.Popen(cmd, stdout = subprocess.PIPE, env=env).communicate()[0]
        return out

    try:
        out = _minimal_ext_cmd(['git', 'rev-parse', 'HEAD'])
        GIT_REVISION = out.strip().decode('ascii')
    except OSError:
        GIT_REVISION = "Unknown"

    return GIT_REVISION

2
मुझे यह पसंद है, बहुत साफ है और कोई बाहरी पुस्तकालय नहीं है
2a पर 13

युजी का जवाब कोड की केवल एक पंक्ति में एक समान समाधान प्रदान करता है जो समान परिणाम उत्पन्न करता है। क्या आप बता सकते हैं कि numpy"न्यूनतम वातावरण का निर्माण" करना क्यों आवश्यक है? (यह मानते हुए कि उनके पास इसका अच्छा कारण है)
एमडी ०४४

मैंने सिर्फ उनके रेपो में इस पर ध्यान दिया, और दिलचस्पी रखने वाले लोगों के लिए इस सवाल में इसे जोड़ने का फैसला किया। मैं विंडोज में विकसित नहीं करता हूं, इसलिए मैंने इसका परीक्षण नहीं किया है, लेकिन मैंने मान लिया था कि envक्रॉस-प्लेटफ़ॉर्म कार्यक्षमता के लिए तानाशाही स्थापित करना आवश्यक था। युजी का जवाब नहीं है, लेकिन शायद यह यूनिक्स और विंडोज दोनों पर काम करता है।
ryanjdillon

Git के दोष को देखते हुए, उन्होंने 11 साल पहले SVN के लिए बग फिक्स के रूप में ऐसा किया: github.com/numpy/numpy/commit/… यह संभव है कि बग फिक्स git के लिए अब आवश्यक नहीं है।
अपराह्न

@ MD004 @ryanjdillon वे स्थानीय सेट करते हैं ताकि .decode('ascii')काम करें - अन्यथा एन्कोडिंग अज्ञात है।
zrr

7

यदि सबप्रोसेस पोर्टेबल नहीं है और आप इस साधारण से कुछ करने के लिए पैकेज स्थापित नहीं करना चाहते हैं तो आप यह भी कर सकते हैं।

import pathlib

def get_git_revision(base_path):
    git_dir = pathlib.Path(base_path) / '.git'
    with (git_dir / 'HEAD').open('r') as head:
        ref = head.readline().split(' ')[-1].strip()

    with (git_dir / ref).open('r') as git_hash:
        return git_hash.readline().strip()

मैंने केवल अपने रेपो पर इसका परीक्षण किया है लेकिन ऐसा लगता है कि यह लगातार काम करता है।


कभी-कभी / refs / नहीं मिलता है, लेकिन वर्तमान प्रतिबद्ध आईडी "पैक-रेफ" में पाया जाता है।
am9417

7

यहाँ ग्रेग के उत्तर का अधिक पूर्ण संस्करण दिया गया है :

import subprocess
print(subprocess.check_output(["git", "describe", "--always"]).strip().decode())

या, यदि स्क्रिप्ट को रेपो के बाहर से बुलाया जा रहा है:

import subprocess, os
os.chdir(os.path.dirname(__file__))
print(subprocess.check_output(["git", "describe", "--always"]).strip().decode())

1
उपयोग करने के बजाय os.chdir, निष्पादन से पहले कार्य निर्देशिका को अस्थायी परिवर्तन करने के लिए cwd=arg का उपयोग किया जा सकता है check_output
मार्क

0

यदि आपके पास किसी कारण से git उपलब्ध नहीं है, लेकिन आपके पास git रेपो (.git फ़ोल्डर पाया जाता है) है, तो आप .it / fetch / heads / [ब्रांच] से प्रतिबद्ध हैश प्राप्त कर सकते हैं।

उदाहरण के लिए, मैंने कमेटी बनाने के लिए रिपॉजिटरी रूट पर निम्न त्वरित और गंदे पायथन स्निपेट का उपयोग किया है:

git_head = '.git\\HEAD'

# Open .git\HEAD file:
with open(git_head, 'r') as git_head_file:
    # Contains e.g. ref: ref/heads/master if on "master"
    git_head_data = str(git_head_file.read())

# Open the correct file in .git\ref\heads\[branch]
git_head_ref = '.git\\%s' % git_head_data.split(' ')[1].replace('/', '\\').strip()

# Get the commit hash ([:7] used to get "--short")
with open(git_head_ref, 'r') as git_head_ref_file:
    commit_id = git_head_ref_file.read().strip()[:7]
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.