2016-07-15 14 views
4

В настоящее время я выполняю Pygit 0.24.1 (вместе с libgit 0.24.1), работая над хранилищем, где у меня есть две ветки (скажем prod и dev).Pygit2: Почему слияние оставляет ветку в нечистом состоянии?

Каждое изменение сначала передается ветке dev и помещается в удаленный репозиторий. Чтобы сделать это, у меня есть этот кусок кода:

repo = Repository('/foo/bar') 
repo.checkout('refs/heads/dev') 

index = repo.index 
index.add('any_file') 
index.write() 

tree = index.write_tree() 
author = Signature('foo', '[email protected]') 
committer = Signature('foo', '[email protected]') 
repo.create_commit('refs/heads/dev', author, committer, 'Just another commit', tree, [repo.head.get_object().hex]) 

up = UserPass('foo', '***') 
rc = RemoteCallbacks(credentials=up) 
repo.remotes['origin'].push(['refs/heads/dev'], rc) 

Это работает очень хорошо, я могу увидеть местный совершить, а также удаленный совершала, а местное репо остается чистым:

ничего совершить, рабочий каталог чистой

Далее я выезд на prod ветви, и я хочу, чтобы объединить ГОЛОВА совершить на dev. Для этого я использую этот другой кусок кода (предполагая, что я всегда начинаю извлеченная к dev отрасли):

head_commit = repo.head 
repo.checkout('refs/heads/prod') 
prod_branch_tip = repo.lookup_reference('HEAD').resolve() 
prod_branch_tip.set_target(head_commit.target) 

rc = RemoteCallbacks(credentials=up) 
repo.remotes['origin'].push(['refs/heads/prod'], rc) 

repo.checkout('refs/heads/dev') 

я на самом деле можно увидеть ветвь объединяемых как локально, так и удаленно, но после этого кусок кода запускается, файл всегда остается в изменен состояние на ветке dev.

На ветке разработчика

Изменения должны быть совершены: (используйте "GIT сброса ГОЛОВУ ...", чтобы убрать из буфера)

модифицирована: any_file

Я совершенно уверен, однако никто не модифицирует этот файл. На самом деле, git diff ничего не показывает. Эта проблема возникает только с уже обработанными файлами (т. Е. Файлами, которые были совершены хотя бы один раз ранее). Когда файлы новы, это отлично работает и оставляет файл в чистом состоянии.

Уверен, что мне не хватает деталей, но я не могу узнать, что это. Почему файл осталось так: изменен?

EDIT: Чтобы уточнить, моя цель - слияние FF (Fast-Forward). Я знаю, что есть некоторая документация о выполнении слияния не FF в документации Pygit2, но я бы предпочел первый метод, потому что он сохраняет хеширование через ветви.

EDIT 2: После того, как @ комментарий Леона, я проверил и действительно, git diff ничего не выводит, а git diff --cached показывает содержание, что файл имел перед тем совершали. Это странно, так как я вижу, что изменения успешно совершены в локальных и удаленных репозиториях, но похоже, что после этого файл снова будет изменен на предыдущий контент ...

Пример этого:

  1. Имея файл с содержанием «12345» поручены + толкали, я заменить эту строку с «54321»
  2. я запускаю код выше
  3. git log показывает файл поручены правильно на удаленном репо я вижу файл с содержанием «54321», в то время как локально git diff --cached показывает это:

    @@ -1 +1 @@ 
    -54321 
    +12345 
    
+0

«* На самом деле,' 'git diff * * ничего не показывает *". Возможно, вы имели в виду "git diff --staged' * ничего не показывает *"? – Leon

+0

@ Leon, пожалуйста, взгляните на * EDIT 2 *, так как я сделал несколько дополнительных тестов и помог мне немного разобраться. – nKn

ответ

3

Я хотел бы объяснить наблюдаемую проблему следующим образом:

head_commit = repo.head 

# This resets the index and the working tree to the old state 
# and records that we are in a state corresponding to the commit 
# pointed to by refs/heads/prod 
repo.checkout('refs/heads/prod') 

prod_branch_tip = repo.lookup_reference('HEAD').resolve() 

# This changes where refs/heads/prod points. The index and 
# the working tree are not updated, but (probably due to a bug in pygit2) 
# they are not marked as gone-out-of-sync with refs/heads/prod 
prod_branch_tip.set_target(head_commit.target) 

rc = RemoteCallbacks(credentials=up) 
repo.remotes['origin'].push(['refs/heads/prod'], rc) 

# Now we must switch to a state corresponding to refs/heads/dev. It turns 
# out that refs/heads/dev points to the same commit as refs/heads/prod. 
# But we are already in the (clean) state corresponding to refs/heads/prod! 
# Therefore there is no need to update the index and/or the working tree. 
# So this simply changes HEAD to refs/heads/prod 
repo.checkout('refs/heads/dev') 

Раствор для быстрой перемотки сук без проверки его. Следующий код лишен описанной проблемы:

head_commit = repo.head 
prod_branch_tip = repo.lookup_branch('prod') 
prod_branch_tip.set_target(head_commit.target) 

rc = RemoteCallbacks(credentials=up) 
repo.remotes['origin'].push(['refs/heads/prod'], rc) 
+0

Это работает, спасибо. Таким образом, единственные существенные различия между моим кодом и вашими - это проверки и способы разрешения 'prod_branch_tip'. Трудно понять, почему этот подход имеет значение, документация об этом не совсем объяснительна, поэтому я сделаю несколько дополнительных тестов, чтобы лучше понять, что происходит. Во всяком случае, ваш ответ правильный, поэтому я отмечаю его как таковой. – nKn

 Смежные вопросы

  • Нет связанных вопросов^_^