5

Using GitPython and I want to call a function only if there is a change to local files after a pull. For example if I make a push on a separate computer. Then pull on the first computer it works as expected but does not provide any output. An ideal output is a list of files changed. Or alternatively just something that told me if the pull had an error, nothing pulled because the branch was up to date or a boolean that changes had happened. I believe I could scrape repo.git.status() but it seems crude. Looking around it looks like I could also compare branches for changes but it seems like a lot of extra code and remote calls. Is there a correct way using just the pull call?

while True:
    repo = git.Repo()
    o = repo.remotes.origin
    o.pull()
    changed = NOT_SURE
    if changed:
        do_something()
    print(repo.git.status())
    time.sleep(POLLING_RATE)

Update: This does work for checking if changes were made but does not give the files changes without extra remote calls

while True:
    print(str(time.ctime())+": Checking for updates")
    repo = git.Repo()
    current_hash = repo.head.object.hexsha
    o = repo.remotes.origin
    o.pull()
    pull_hash = repo.head.object.hexsha
    if current_hash != pull_hash:
        print("files have changed")
    else:
        print("no changes")

    time.sleep(config.GIT_POLL_RATE)
Ryan Mills
  • 939
  • 1
  • 10
  • 23
  • To determine the difference between the newest commit (after pulling) and an earlier commit you would use `git diff`. I can't tell you how to do that in GitPython, however. – mkrieger1 May 31 '18 at 22:27
  • Comparing hashes tells you whether you received new commits by pulling. It is possible, however, that there are no differences in the files between the two commits. – mkrieger1 May 31 '18 at 22:30

2 Answers2

4

I appreciate that this is two years late, however, I hope it may still be of some use.

I have just written pullcheck, a simple script to pull from a repo, check for changes then restart a target if changes are found. I found that this method was able to identify changes from the pull.

def git_pull_change(path):
    repo = git.Repo(path)
    current = repo.head.commit

    repo.remotes.origin.pull()

    if current == repo.head.commit:
        print("Repo not changed. Sleep mode activated.")
        return False
    else:
        print("Repo changed! Activated.")
        return True
James Geddes
  • 742
  • 3
  • 10
  • 35
0

You could use git-fetch as well if you want just check what kind of changes were on the remote side.

And if you want to print changes, you probably should explore git-diff, e.g.:


POLLING_RATE = 10
REM_BRANCH = 'master'

def pretty_diff(diff):
    for cht in diff.change_type:
        changes = list(diff.iter_change_type(cht))
        if len(changes) == 0:
            continue
        print("Changes type:", cht)
        for d in changes:
            print(d.b_path)


while True:
    repo = git.Repo('.')
    current_hash = repo.head.object.hexsha
    o = repo.remotes.origin
    o.fetch()
    changed = o.refs[REM_BRANCH].object.hexsha != current_hash
    if changed:
        # do_something()
        diff = repo.head.commit.diff(o.refs[REM_BRANCH].object.hexsha)
        pretty_diff(diff)
    time.sleep(POLLING_RATE)

git-diff supports different change types:

print(diff.change_type)
#('A', 'C', 'D', 'R', 'M', 'T')

You may do different things for the different change types.

eli
  • 61
  • 1
  • 2