gpt4 book ai didi

Git2go : How to handle simple merge conflicts

转载 作者:IT王子 更新时间:2023-10-29 01:45:20 26 4
gpt4 key购买 nike

对于一个简单的实时编码环境,我正在编写一个 git add、commit 和 push 函数,它工作正常,除了冲突的情况,当两个用户在文件的同一部分编码时。它正确执行冲突分析并加载结果:

// Live-Editor, Processing / Javascript
fill(130, 52, 130);
<<<<<<< HEAD
textSize(130);
=======
textSize(120);
>>>>>>> master
text( "𝄠",160, 100);

显示 git 风格的差异。但是当我随后在编辑器中进行更改并再次添加/提交/推送时,它会导致相同的冲突。就像它不“记得”冲突已经存在并且再次出现一样。 (与 git 命令行行为不同。)

这是我的代码(我删除了错误处理以使其更短......)

// Add
repo, err := git.OpenRepository(dir)
index, err := repo.Index()
err = index.AddAll([]string{}, git.IndexAddDefault, nil)
err = index.Write()
treeId, err := index.WriteTreeTo(repo)
tree, err := repo.LookupTree(treeId)

// Commit
sig := &git.Signature{
Name: userName,
Email: userName + "@" + beego.AppConfig.String("userdata::emailserver"),
When: time.Now(),
}
var currentCommit *git.Oid
if firstCommit == true {
_, err = repo.CreateCommit("HEAD", sig, sig, message, tree)
} else {
currentBranch, err := repo.Head()
currentTip, err := repo.LookupCommit(currentBranch.Target())
currentCommit, err = repo.CreateCommit("HEAD", sig, sig, message, tree, currentTip)
}

remote, err := repo.LookupRemote("origin")

// Pull
if firstCommit == false {
// Pull possible changes from remote repo
err = remote.Fetch([]string{}, nil, "")
remoteBranch, err := repo.LookupReference("refs/remotes/origin/master")
annotatedCommit, err := repo.AnnotatedCommitFromRef(remoteBranch)

// Do the merge analysis
mergeHeads := make([]*git.AnnotatedCommit, 1)
mergeHeads[0] = annotatedCommit
analysis, _, err := repo.MergeAnalysis(mergeHeads)

if analysis&git.MergeAnalysisUpToDate == 0 && analysis&git.MergeAnalysisNormal != 0 {

err := repo.Merge([]*git.AnnotatedCommit{annotatedCommit}, nil, nil)

// Check for conflicts
index, err := repo.Index()
if index.HasConflicts() {
err = index.Write()
return errors.New("Conflicts")
}

// No unsolvable conflicts, commit it
treeId, err := index.WriteTree()
tree, err := repo.LookupTree(treeId)
localCommit, err := repo.LookupCommit(currentCommit)
remoteCommit, err := repo.LookupCommit(remoteBranch.Target())
repo.CreateCommit("HEAD", sig, sig, "Merge commit", tree, localCommit, remoteCommit)
repo.StateCleanup()
}
}

// Push
err = remote.Push([]string{"refs/heads/master"}, nil, sig, message)

我猜关键部分在 //Check for conflicts 之后 不知何故,这使 git 目录处于一种状态,让它执行相同的分析。我考虑过在用户做出更改并再次提交项目后不进行分析,但有可能在此期间另一个用户已经在远程仓库中更改了某些内容。

如何处理与 git2go 的此类冲突的好方法?

最佳答案

我解决了这个问题。碰撞检测工作正常。如果发生无法自动解决的冲突,则将控制权交还给用户。他进行了更改,但在冲突分析再次发生之前,这些更改并未提交。

这里是完整的代码(“merge 提交(如果 - 现在希望解决 - 冲突)是至关重要的。”之后的部分):

//////////////////////////////////////////////////////////
// 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
}

关于Git2go : How to handle simple merge conflicts,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37072576/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com