2015-01-02 6 views
2

Я пытаюсь реализовать некоторые «фарфоровые» команды, используя pygit2. Кажется, что я столкнулся с небольшим количеством дорожного блока, выполняя притяжение. В частности, самый простой корпус, быстрый вперед.Реализация Pull с Pygit2

Установка:

У меня есть два GIT хранилищу. Один «удаленный» и один «локальный». Я делаю одну фиксацию на удаленном репо, а затем создаю локальное репо, используя pygit2 clone_repository(). Я делаю последующую фиксацию на пульте дистанционного управления, а затем пытаюсь запустить функцию pull(), описанную ниже.

Моя реализация:

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') 

Full Source

После быстрой перемотки вперед немного моего кода выполняет мой индекс больше не чист, и я понятия не имею, почему. Глядя на git-журнал, он выглядит успешным. Моя голова и главная ветвь теперь указывают на самую последнюю фиксацию на удаленном репо. Однако почему remote_repo_test.txt изменен в процессе работы set_target().

В Выходах:

тянущего заявление печати:

abfe58ce5098e106a14263df725247bc1f4b22d2 
{} 
{'remote_repo_test.txt': 2} 

Git журнал:

* 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 Статус:

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 содержание:

Version 1. 

Вопросы, относящиеся без ответов:

Мысли?

ответ

3

Первое решение (не рекомендуется):

Вы должны не сделать это. Так можно потерять работу. Однако он работает как хакерское решение.

master_ref = repo.lookup_reference('refs/heads/master') 
master_ref.set_target(remote_master_id) 
# Terrible hack to fix set_target() screwing with the index 
repo.reset(master_ref.target, pygit2.GIT_RESET_HARD) 

Full source

Второе решение:

Это один представляется перспективным. После долгих проб и ошибок я, возможно, нашел решение.Если вы проверяете объект дерева, на который хотите установить таргетинг , перед вы обновляете ссылку, в которой он работает. Индекс чист, как можно было бы ожидать при запуске git pull или git merge

repo.checkout_tree(repo.get(remote_master_id)) 
master_ref = repo.lookup_reference('refs/heads/master') 
master_ref.set_target(remote_master_id) 
repo.head.set_target(remote_master_id) 

Full source