我解決了這個問題。碰撞檢測工作正常。如果發生不能自動解決的衝突,控制權將交還給用戶。他做出了改變,在衝突分析再次發生之前,這些改變沒有發生。
下面是完整的代碼(後一節「合併提交(在以下情況下 - 現在希望解決 - 衝突)是至關重要的。」):
//////////////////////////////////////////////////////////
// GitAddCommitPush
func GitAddCommitPush(userName string, dir string, message string, firstCommit bool) error {
///////////////////////////////////////////////////////////////////////
// Add
//
// 1 Open repository
repo, err := git.OpenRepository(dir)
if err != nil {
beego.Error("OpenRepository - ", err)
}
// 2 Retrieve index
index, err := repo.Index()
if err != nil {
beego.Error("Index - ", err)
}
// 3 Remember if we had conflicts before we added everything to the index
indexHadConflicts := index.HasConflicts()
// 4 Add everything to the index
err = index.AddAll([]string{}, git.IndexAddDefault, nil)
if err != nil {
beego.Error("AddAll - ", err)
}
// 5 Write the index (so git knows about it)
err = index.Write()
if err != nil {
beego.Error("Write - ", err)
}
// 6 Write the current index tree to the repo
treeId, err := index.WriteTreeTo(repo)
if err != nil {
beego.Error("WriteTreeTo - ", err)
}
/////////////////////////////////////////////////////////////////////////////////////////////
// Commit
//
// 1 Retrieve the tree we just wrote (git's reference of it that it made in the last step)
tree, err := repo.LookupTree(treeId)
if err != nil {
beego.Error("LookupTree - ", err)
}
// 2 Create a signature
sig := &git.Signature{
Name: userName,
Email: userName + "@" + beego.AppConfig.String("userdata::emailserver"),
When: time.Now(),
}
// 3 Get remote now (as we need it for both, fetch and later push)
remote, err := repo.LookupRemote("origin")
if err != nil {
remote, err = repo.CreateRemote("origin", repo.Path())
if err != nil {
beego.Error("CreateRemote - ", err)
}
}
// 4 Read the remote branch
remoteBranch, err := repo.LookupReference("refs/remotes/origin/master")
if err != nil {
beego.Error("Fetch 2 - ", err)
}
// 5 Determine if this is a first commit ...
if firstCommit == true {
// 5a ... then create a new one
_, err = repo.CreateCommit("HEAD", sig, sig, message, tree)
} else {
// 5b ... or retrieve current head
currentBranch, err := repo.Head()
if err != nil {
beego.Error("Head - ", err)
}
// 6 Retrieve current commit
currentTip, err := repo.LookupCommit(currentBranch.Target())
if err != nil {
beego.Error("LookupCommit - ", err)
}
// 7 Create a new one on top
currentCommit, err := repo.CreateCommit("HEAD", sig, sig, message, tree, currentTip)
if err != nil {
beego.Error("CreateCommit - ", err)
}
////////////////////////////////////////////////////////////////////////////////////
// Merge commit (in case of -- now hopefully resolved -- conflicts)
//
// 1 If there were conflicts, do the merge commit
if indexHadConflicts == true {
// 2 Retrieve the local commit
localCommit, err := repo.LookupCommit(currentCommit)
if err != nil {
beego.Error("Fetch 11 - ", err)
}
// 3 Retrieve the remote commit
remoteCommit, err := repo.LookupCommit(remoteBranch.Target())
if err != nil {
beego.Error("Fetch 12 - ", err)
}
// 4 Create a new one
repo.CreateCommit("HEAD", sig, sig, "Merge commit", tree, localCommit, remoteCommit)
// 5 Clean up
repo.StateCleanup()
}
///////////////////////////////////////////////////////////////////////////////////
// Pull (Fetch and Commit)
//
// 1 Fetch it (pull without commit)
err = remote.Fetch([]string{}, nil, "")
if err != nil {
beego.Error("Fetch 1 - ", err)
}
// 2 Perform an annotated commit
annotatedCommit, err := repo.AnnotatedCommitFromRef(remoteBranch)
if err != nil {
beego.Error("Fetch 3 - ", err)
}
// 3 Do the merge analysis
mergeHeads := make([]*git.AnnotatedCommit, 1)
mergeHeads[0] = annotatedCommit
analysis, _, err := repo.MergeAnalysis(mergeHeads)
if err != nil {
beego.Error("Fetch 4 - ", err)
}
// 4 Check if something happend
if analysis&git.MergeAnalysisUpToDate == 0 && analysis&git.MergeAnalysisNormal != 0 {
// 5 Yes! First just merge changes
if err := repo.Merge([]*git.AnnotatedCommit{annotatedCommit}, nil, nil); err != nil {
beego.Error("Fetch 5 - ", err)
}
// 6 Retrieve the index after that treatment
index, err := repo.Index()
if err != nil {
beego.Error("Fetch 6 - ", err)
}
// 7 Check for conflicts
if index.HasConflicts() {
// 7a There are not automaticly solvable conflicts ... give them back to the user
beego.Trace("Conflicts! Write new index and return.", index)
err = index.Write()
if err != nil {
beego.Error("Write - ", err)
}
return errors.New("Conflicts")
}
// 8 Write the new tree
treeId, err := index.WriteTree()
if err != nil {
beego.Error("Fetch 9 - ", err)
}
// 9 Retrieve the new tree
tree, err := repo.LookupTree(treeId)
if err != nil {
beego.Error("Fetch 10 - ", err)
}
// 10 Retrieve the local commit
localCommit, err := repo.LookupCommit(currentCommit)
if err != nil {
beego.Error("Fetch 11 - ", err)
}
// 11 Retrieve the remote commit
remoteCommit, err := repo.LookupCommit(remoteBranch.Target())
if err != nil {
beego.Error("Fetch 12 - ", err)
}
// 12 Create a new one
repo.CreateCommit("HEAD", sig, sig, "Merge commit", tree, localCommit, remoteCommit)
// 13 Clean up
repo.StateCleanup()
}
}
//////////////////////////////////////////////////////////////////////////////////////////////////////
// Push
err = remote.Push([]string{"refs/heads/master"}, nil, sig, message)
if err != nil {
beego.Error("Push - ", err)
}
return err
}
此代碼不會告訴你做什麼當發生衝突時,這似乎就是你所問的。分析不會因爲你在合併而改變,因爲HEAD和遠程分支不會改變,但是這並沒有告訴你任何關於你現在正在進行的合併。 –
是的,看起來我在第一個循環中做了所有事情,直到我檢測到衝突並返回編輯器,告訴用戶進行更改並再次保存項目。然後當用戶保存該項目時,我只需調用相同的函數並獲得相同的結果。我只是不知道如何檢測這個函數,索引處於不同的狀態,有不同的路徑沒有彙集在一起。你有一個提示,我怎麼能找到這個? – Michael
分析與當前操作無關。檢查當前的操作,看看你是否在合併,並且要求索引查看是否有衝突,這樣可以避免提交;如果沒有衝突,那麼你可以把它寫成一棵樹,並使用那棵樹創建一個提交,就像任何其他時間一樣 –