为了账号安全,请及时绑定邮箱和手机立即绑定

Git2go:如何处理简单的合并冲突

Git2go:如何处理简单的合并冲突

Go
幕布斯7119047 2022-01-10 10:59:10
对于一个简单的实时编码环境,我正在编写一个 git add、commit 和 push 函数,当两个用户在文件的同一部分编码时,除了冲突的情况外,它工作正常。它正确执行冲突分析并加载结果:// Live-Editor, Processing / Javascriptfill(130, 52, 130);<<<<<<< HEADtextSize(130);=======textSize(120);>>>>>>> mastertext( "𝄠",160, 100);显示 git 风格的差异。但是当我在编辑器中进行更改并再次添加/提交/推送时,它会导致同样的冲突。就好像它没有“记住”冲突已经存在并再次出现。(与 git 命令行行为不同。)这是我的代码(我去掉了错误处理以使其更短......)// Addrepo, 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)// Commitsig := &git.Signature{    Name:  userName,    Email: userName + "@" + beego.AppConfig.String("userdata::emailserver"),    When:  time.Now(),}var currentCommit *git.Oidif 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")// Pullif 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)        }    }}// Pusherr = remote.Push([]string{"refs/heads/master"}, nil, sig, message)我猜关键部分是在// Check for conflicts不知何故使 git 目录处于一种让我们执行相同分析的状态之后。我考虑过在用户进行更改并再次提交项目后不进行分析,但与此同时另一个用户可能已经更改了远程仓库中的某些内容。如何用 git2go 处理此类冲突的好方法?
查看完整描述

1 回答

?
暮色呼如

TA贡献1853条经验 获得超9个赞

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


这是完整的代码(“合并提交(以防——现在希望解决——冲突)之后的部分至关重要。”):


//////////////////////////////////////////////////////////

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

}



查看完整回答
反对 回复 2022-01-10
  • 1 回答
  • 0 关注
  • 127 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信