Working with Git in Python on Windows

Disable Python aliases:

Do not download ZIP archive, but install Python from EXE package in Windows Sandbox and copy its binaries to the working machine using

Compress-Archive -Path .\Python313\ -DestinationPath archive.zip

At least it should contain Scripts folder:

DLLs
Doc
include
Lib
libs
Scripts
tcl
LICENSE.txt
NEWS.txt
python.exe
python3.dll
python313.dll
pythonw.exe
vcruntime140.dll
vcruntime140_1.dll

Install GitPython:

python -m pip install gitpython
python -m pip install colorama

Add the following alias to ~/.bashrc:

alias ca='/c/dev/tools/Python313/python /c/dev/repos/bbs/gitpy/commit-all.py'

And use a script that commits and pushes all the submodules:

import git
from colorama import Fore, Style

def get_repo_name_from_url(url: str) -> str:
    last_slash_index = url.rfind("/")
    last_suffix_index = url.rfind(".git")
    if last_suffix_index < 0:
        last_suffix_index = len(url)

    if last_slash_index < 0 or last_suffix_index <= last_slash_index:
        raise Exception("Badly formatted url {}".format(url))

    return url[last_slash_index + 1:last_suffix_index]

class Object:
    pass

def detect_changes(repo):

    diff = repo.git.diff(None, name_only=True)
    untracked_files = repo.untracked_files

    if diff or untracked_files:
        change = Object()
        change.name = get_repo_name_from_url(repo.remotes[0].config_reader.get("url"))
        change.repo = repo
        change.diff = diff
        change.untracked_files = untracked_files
        return change

repo_changes = []

def append_changes(repo):
    change = detect_changes(repo)
    if change:
        repo_changes.append(change)

root_repo = git.Repo()

for submodule in root_repo.submodules:
    repo = submodule.module()
    append_changes(repo)

append_changes(root_repo)

def is_pushed(push_info: git.remote.PushInfo) -> bool:
    valid_flags = {push_info.FAST_FORWARD, push_info.NEW_HEAD}  # UP_TO_DATE flag is intentionally skipped.
    return push_info.flags in valid_flags  # This check can require the use of & instead.

if repo_changes:

    for change in repo_changes:

        repo = change.repo

        print(f"{Fore.GREEN}{change.name}{Style.RESET_ALL} on branch {Fore.YELLOW}{repo.active_branch.name}{Style.RESET_ALL}:")

        if change.diff:
            print(f"{Fore.RED}{change.diff}{Style.RESET_ALL}")

        if change.untracked_files:
            print(f"\t{Fore.RED}{change.untracked_files}{Style.RESET_ALL}")

    commit_message = input("Commit message: ")

    if commit_message:

        for change in repo_changes:

            repo = change.repo
            repo.git.add(all=True)
            repo.git.commit('-m', commit_message)
            origin = repo.remote('origin')
            info = origin.push()[0]
            if is_pushed(info):
                print("Pushed.")
            else:
                print("The changes has not been pushed.")
                break

    else:

        print("Empty message. Bye.")

else:

    print("No changes to commit.")

7 Responses to Working with Git in Python on Windows

  1. dmitriano says:

    ModuleNotFound : No module named “git”
    https://stackoverflow.com/questions/67459422/modulenotfound-no-module-named-git
    python3 -m pip install gitpython

  2. dmitriano says:

    Error running ‘pip install’: “ImportError: No module named pip” [duplicate]
    https://stackoverflow.com/questions/18363022/error-running-pip-install-importerror-no-module-named-pip
    sudo apt install python3-pip

  3. dmitriano says:

    Are f-strings supposed to work in Python 3.4?
    https://stackoverflow.com/questions/38865348/are-f-strings-supposed-to-work-in-python-3-4
    pip install future-fstrings

  4. dmitriano says:

    Getting Started with GitPython
    https://azzamsa.com/n/gitpython-intro/

  5. dmitriano says:

    https://stackoverflow.com/questions/41836988/git-push-via-gitpython
    def git_push():
    try:
    repo = Repo(PATH_OF_GIT_REPO)
    repo.git.add(update=True)
    repo.index.commit(COMMIT_MESSAGE)
    origin = repo.remote(name=’origin’)
    origin.push()
    except:
    print(‘Some error occured while pushing the code’)

  6. dmitriano says:

    https://stackoverflow.com/questions/31835812/gitpython-how-to-commit-updated-submodule
    repos.git.add(submodule.path)
    repos.index.commit(“updated submodule to ‘wanted commit'”)

    https://stackoverflow.com/questions/22949068/using-gitpython-how-do-i-do-git-submodule-update-init
    for submodule in repo.submodules:
    submodule.update(init=True)

Leave a Reply

Your email address will not be published. Required fields are marked *