Pygit2:为什么合并会使分支处于不洁状态?

时间:2016-07-15 19:45:11

标签: python git python-2.7 libgit2 pygit2

我目前正在运行Pygit 0.24.1(以及libgit 0.24.1),在一个存储库中工作,我有两个分支(比如proddev)。

每次更改都首先提交到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', 'foo@bar')
committer = Signature('foo', 'foo@bar')
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上的HEAD提交。为此,我使用另一段代码(假设我总是开始签出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')

我实际上可以看到分支在本地和远程合并,在这段代码运行后,提交的文件始终保持在分支上的修改状态{ {1}}。

  

在分支开发

上      

要提交的更改:   (使用" git reset HEAD ..."取消暂停)

     

修改:any_file

我完全确定没有人正在修改该文件。实际上,dev没有显示任何内容。此问题仅在已提交的文件(即先前至少提交过一次的文件)中发生。当文件是新文件时,这样可以完美地工作并使文件处于干净状态。

我确定我错过了一些细节,但我无法找出它是什么。为什么文件保留为修改

编辑:为了澄清,我的目标是进行FF(快进)合并。我知道有关于在Pygit2文档中进行非FF合并的一些文档,但是我更喜欢第一种方法,因为它通过分支保持提交哈希值。

编辑2 :在@Leon的评论之后,我进行了双重检查,确实git diff显示没有输出,git diff显示文件的内容< em>在提交之前。这是奇怪的,因为我可以看到更改成功提交到本地和远程存储库,但看起来之后文件再次更改为以前的内容...

一个例子:

  1. 拥有包含内容的文件&#39; 12345&#39;提交+推送,我用&#39; 54321&#39;
  2. 替换该字符串
  3. 我运行上面的代码
  4. git diff --cached显示正确提交的文件,在远程仓库中我看到包含内容的文件&#39; 54321&#39;,而本地git log显示:

    git diff --cached

1 个答案:

答案 0 :(得分: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)