Найдите корень репозитория git, где находится файл

При работе в Python (например, запустите script), как я могу найти путь к корню репозитория git, где живет script?

До сих пор я знаю, что могу получить текущий путь:

path_to_containing_folder = os.path.dirname(os.path.realpath(__file__))

Как я могу узнать, где живет репозиторий git?

Ответ 1

Используйте модуль GitPython http://gitpython.readthedocs.io/en/stable/.

pip install gitpython

Предположим, что у вас есть локальный репозиторий Git в /path/to/.git. Нижеприведенный пример получает /path/to/your/file как вход, он правильно возвращает корень Git как /path/to/.

import git

def get_git_root(path):

        git_repo = git.Repo(path, search_parent_directories=True)
        git_root = git_repo.git.rev_parse("--show-toplevel")
        print git_root

if __name__ == "__main__":
    get_git_root("/path/to/your/file")

Ответ 2

Поиск каталога .git не будет работать во всех случаях. Правильная команда git:

git rev-parse --show-toplevel

Ответ 3

Я написал небольшой модуль python для этой задачи: https://github.com/MaxNoe/python-gitpath

Установить с помощью pip install git+https://github.com/maxnoe/python-gitpath

Использование:

import gitpath

print(gitpath.root())
print(gitpath.abspath('myfile.txt'))

gitpath.abspath(relative_path) вернет абсолютный путь на вашем компьютере для пути, заданного относительно корня репозитория git.

Код для получения корня частично получен из комментария Ryne Everetts:

from subprocess import check_output, CalledProcessError
from functools import lru_cache

@lru_cache(maxsize=1)
def root():
    ''' returns the absolute path of the repository root '''
    try:
        base = check_output('git rev-parse --show-toplevel', shell=True)
    except CalledProcessError:
        raise IOError('Current working directory is not a git repository')
    return base.decode('utf-8').strip()

Кэширование делает второй вызов root() ca. 3500 раз быстрее (измеряется с помощью ipython и %%timeit)

Ответ 4

Модуль GitPython предоставляет этот атрибут прямо из коробки:

import git

repo = git.Repo('.', search_parent_directories=True)
repo.working_tree_dir

Ответ 5

Эта функция является общей (не зависит от внешнего модуля или вызова команды git). Он ищет путь от заданного пути, чтобы найти первый, содержащий каталог .git.

def find_vcs_root(test, dirs=(".git",), default=None):
    import os
    prev, test = None, os.path.abspath(test)
    while prev != test:
        if any(os.path.isdir(os.path.join(test, d)) for d in dirs):
            return test
        prev, test = test, os.path.abspath(os.path.join(test, os.pardir))
    return default

Пример использования:

import os
print(vcs_root(os.path.dirname(__file__)))

Или проверьте наличие другого контроля версий:

import os
print(vcs_root(os.path.dirname(__file__)), dirs=(".hg", ".git", ".svn"))

Ответ 6

Я не знаю много о python, но я думаю, что вы можете продолжать каталоги с помощью

os.path.abspath(os.path.join(dir, '..'))

Пока вы не обнаружите каталог .git (os.walk может помочь)

Ответ 7

Без каких-либо внешних библиотек:

import subprocess

def getGitRoot():
    return subprocess.Popen(['git', 'rev-parse', '--show-toplevel'], stdout=subprocess.PIPE).communicate()[0].rstrip().decode('utf-8')