I am trying to implement some 'porcelain' commands using pygit2. It seems that I have run into a bit of road block while implementing pull. Specifically the easiest pull case, a fast forward.
Setup:
I have two git repos. One 'remote' and one 'local'. I make one commit on the remote repo and then create the local repo using pygit2's clone_repository(). I make a subsequent commit on the remote and then attempt to run the pull() function outlined below.
My implementation:
def pull(repo, remote_name='origin'):
    for remote in repo.remotes:
        if remote.name == remote_name:
            remote.fetch()
            remote_master_id = repo.lookup_reference('refs/remotes/origin/master').target
            merge_result, _ = repo.merge_analysis(remote_master_id)
            # Up to date, do nothing
            if merge_result & pygit2.GIT_MERGE_ANALYSIS_UP_TO_DATE:
                return
            # We can just fastforward
            elif merge_result & pygit2.GIT_MERGE_ANALYSIS_FASTFORWARD:
                print repo.head.target
                print repo.status()
                master_ref = repo.lookup_reference('refs/heads/master')
                master_ref.set_target(remote_master_id)
                repo.head.set_target(master_ref)
                repo.checkout_head()
                print repo.status()
            elif merge_result & pygit2.GIT_MERGE_ANALYSIS_NORMAL:
                repo.merge(remote_master_id)
                print repo.index.conflicts
                assert repo.index.conflicts is None, 'Conflicts, ahhhh!'
                user = repo.default_signature
                tree = repo.index.write_tree()
                commit = repo.create_commit('HEAD',
                                            user,
                                            user,
                                            'Merge!',
                                            tree,
                                            [repo.head.target, remote_master_id])
                repo.state_cleanup()
            else:
                raise AssertionError('Unknown merge analysis result')
After the fast forward bit of my code executes, my index is no longer clean and I have no idea why. Looking at the git-log, it looks successful. My head and the master branch are now pointing at the most recent commit on the remote repo. However, why was remote_repo_test.txt modified in the process of running set_target(). 
The Outputs:
The pull print statements:
abfe58ce5098e106a14263df725247bc1f4b22d2
{}
{'remote_repo_test.txt': 2} 
Git log:
* commit b1842f03efe959e93ebad197f36d50ee658e71a4
| Author: Michael Boselowitz <xxx>
| Date:   Fri Jan 2 17:21:45 2015 -0500
| 
|     Version 2 of test.txt on remote_repo
| 
| diff --git a/remote_repo_test.txt b/remote_repo_test.txt
| index a1665f0..13f7f3f 100644
| --- a/remote_repo_test.txt
| +++ b/remote_repo_test.txt
| @@ -1,2 +1,4 @@
|  Version 1.
|  
| +Version 2.
| +
|  
* commit abfe58ce5098e106a14263df725247bc1f4b22d2
  Author: Michael Boselowitz <xxx>
  Date:   Fri Jan 2 17:21:45 2015 -0500
      Version 1 of test.txt on remote_repo
  diff --git a/remote_repo_test.txt b/remote_repo_test.txt
  new file mode 100644
  index 0000000..a1665f0
  --- /dev/null
  +++ b/remote_repo_test.txt
  @@ -0,0 +1,2 @@
  +Version 1.
  +
Git status:
On branch master
Your branch is up-to-date with 'origin/master'.
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)
    modified:   remote_repo_test.txt
remote_repo_test.txt content:
Version 1.
Related Questions without Answers:
- pulling and integrating remote changes with pygit2
- Implementing 'git pull' with libgit2?
- Performing a “fast-forward” merge with Rugged
Thoughts?
 
    