Как добавить новые файлы в GitHub?

Я создал новый репозиторий на github.com, а затем клонировал его на свою локальную машину с помощью

git clone https://github.com/usrname/mathematics.git

Я добавил 3 новых файла в папку mathematics

$ tree 
.
├── LICENSE
├── numerical_analysis
│   └── regression_analysis
│       ├── simple_regression_analysis.md
│       ├── simple_regression_analysis.png
│       └── simple_regression_analysis.py

Теперь я хотел бы загрузить 3 новых файла в свой GitHub, используя Python, а точнее, PyGithub. Вот что я пробовал:

#!/usr/bin/env python
# *-* coding: utf-8 *-*
from github import Github

def main():
    # Step 1: Create a Github instance:
    g = Github("usrname", "passwd")
    repo = g.get_user().get_repo('mathematics')

    # Step 2: Prepare files to upload to GitHub
    files = ['mathematics/numerical_analysis/regression_analysis/simple_regression_analysis.py', 'mathematics/numerical_analysis/regression_analysis/simple_regression_analysis.png']

    # Step 3: Make a commit and push
    commit_message = 'Add simple regression analysis'

    tree = repo.get_git_tree(sha)
    repo.create_git_commit(commit_message, tree, [])
    repo.push()

if __name__ == '__main__':
    main()

Я не знаю

  • как получить строку sha для repo.get_git_tree
  • как мне установить соединение между шагами 2 и 3, то есть нажатие определенных файлов

Лично Документация PyGithub не читается. Я не могу найти правильный api после долгого поиска.

Ответ 1

Я попытался использовать API GitHub для совершения нескольких файлов. Эта страница для Git API данных говорит, что она должна быть "довольно простой". Результаты этого исследования см. этот ответ.

Я рекомендую использовать что-то вроде GitPython:

from git import Repo

repo_dir = 'mathematics'
repo = Repo(repo_dir)
file_list = [
    'numerical_analysis/regression_analysis/simple_regression_analysis.py',
    'numerical_analysis/regression_analysis/simple_regression_analysis.png'
]
commit_message = 'Add simple regression analysis'
repo.index.add(file_list)
repo.index.commit(commit_message)
origin = repo.remote('origin')
origin.push()

Примечание.. Эта версия script была запущена в родительском каталоге репозитория.

Ответ 2

Я могу дать вам некоторую информационную поддержку, но также и одно конкретное решение.

Здесь вы можете найти примеры добавления новых файлов в ваш репозиторий и здесь - это видеоурок для этого.

Ниже вы можете увидеть список пакетов python, которые работают с GitHub, найденные на странице разработчика GitHub:

Но также вы можете нажимать свои файлы с командами в IPython, если вам нужно:

In [1]: import subprocess
In [2]: print subprocess.check_output('git init', shell=True)
Initialized empty Git repository in /home/code/.git/
In [3]: print subprocess.check_output('git add .', shell=True)
In [4]: print subprocess.check_output('git commit -m "a commit"', shell=True)

Ответ 3

Если документация PyGithub непригодна для использования (и она не выглядит так), и вы просто хотите нажать фиксацию (не делая ничего, что связано с проблемами, конфигурацией репо и т.д.), вам, вероятно, было бы лучше напрямую взаимодействовать с git, либо вызывая исполняемый файл git, либо используя библиотеку обертки, такую ​​как GitPython.

Использование git непосредственно с чем-то вроде subprocess.Popen, которое вы упомянули, вероятно, будет легче на кривой наклона, но также более сложным в долгосрочной перспективе для обработки ошибок и т.д., так как у вас действительно нет хороших абстракций чтобы пройти, и вам придется самостоятельно разбираться.

Избавление от PyGithub также освобождает вас от привязки к GitHub и его API, позволяя вам нажимать на любую репо, даже другую папку на вашем компьютере.

Ответ 4

Примечание.. Эта версия script была вызвана из репозитория GIT, потому что я удалил имя репозитория из путей к файлу.

Наконец-то я понял, как использовать PyGithub для совершения нескольких файлов:

import base64
from github import Github
from github import InputGitTreeElement

token = '5bf1fd927dfb8679496a2e6cf00cbe50c1c87145'
g = Github(token)
repo = g.get_user().get_repo('mathematics')
file_list = [
    'numerical_analysis/regression_analysis/simple_regression_analysis.png',
    'numerical_analysis/regression_analysis/simple_regression_analysis.py'
]
commit_message = 'Add simple regression analysis'
master_ref = repo.get_git_ref('heads/master')
master_sha = master_ref.object.sha
base_tree = repo.get_git_tree(master_sha)
element_list = list()
for entry in file_list:
    with open(entry, 'rb') as input_file:
        data = input_file.read()
    if entry.endswith('.png'):
        data = base64.b64encode(data)
    element = InputGitTreeElement(entry, '100644', 'blob', data)
    element_list.append(element)
tree = repo.create_git_tree(element_list, base_tree)
parent = repo.get_git_commit(master_sha)
commit = repo.create_git_commit(commit_message, tree, [parent])
master_ref.edit(commit.sha)
""" An egregious hack to change the PNG contents after the commit """
for entry in file_list:
    with open(entry, 'rb') as input_file:
        data = input_file.read()
    if entry.endswith('.png'):
        old_file = repo.get_contents(entry)
        commit = repo.update_file('/' + entry, 'Update PNG content', data, old_file.sha)

Если я попытаюсь добавить необработанные данные из PNG файла, вызов create_git_tree в конечном итоге вызывает json.dumps в Requester.py, что вызывает следующее исключение:

UnicodeDecodeError: 'utf8' codec can't decode byte 0x89 in position 0: invalid start byte

Я работаю над этой проблемой base64, кодируя данные PNG и фиксируя это. Позже я использую метод update_file для изменения данных PNG. Это приводит к двум отдельным фиксациям в репозитории, который, вероятно, не тот, который вы хотите.

Ответ 5

import subprocess
p = subprocess.Popen("git rev-parse HEAD".split(), stdout=subprocess.PIPE)
out, err = p.communicate()
sha = out.strip()

Вероятно, есть способ сделать это с PyGithub, но это должно работать для быстрого взлома.