2016-05-06 8 views
2

シンプルなライブコーディング環境では、git add、commit、push関数を書いていますが、2人のユーザーが同じ部分をコーディングしている場合ファイルの競合分析を正しく実行し、結果をロードします。Git2go:単純なマージの競合の処理方法

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

gitスタイルの違いを示します。しかし、私がエディタで変更を行い、再度コミット/プッシュを追加すると、同じ矛盾が生じます。それは紛争がすでにそこにあったことを覚えておらず、再びそれを提示するようなものです。 (とは異なりgitのコマンドラインの動作。)ここで

は、私は// Check for conflictsはどういうわけかそれが去った後、クリティカルセクションがあると思います私のコード(私はそれを短くするために出てエラー処理をした...)

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

ですgitディレクトリを同じ解析を実行できる状態にします。私は、ユーザーが変更を加えてプロジェクトを再コミットした後で分析をしないと考えましたが、その間に別のユーザーが既にリモートリポジトリ内の何かを変更している可能性があります。

git2goとのこのような競合をうまく処理するにはどうすればよいですか?

+0

:ここ

は、完全なコード(「 - - 今、うまくいけば解決コンフリクト)重大である場合には(コミットマージ」の後のセクション)であります紛争が起きたときに、あなたが尋ねているように思えます。 HEADとリモートブランチは変更されていないので、あなたがマージしているという理由だけで分析は変更されませんが、現在行っているマージについては何も教えてくれません。 –

+0

はい、コンフリクトを検出してエディタに戻り、変更を加えてプロジェクトを再度保存するように指示するまで、最初のループですべてを正しく実行しているようです。その後、ユーザーがプロジェクトを保存するときに、私は同じ関数を呼び出して同じ結果を得ます。私はこの機能でどのように検出するか、索引が異なる状態にあること、一緒に集められない異なる経路があることは分かりません。あなたはヒントを持っています、私はこれについてどのように知ることができますか? – Michael

+0

分析は現在の操作とは関係ありません。現在の操作をチェックして、マージしているかどうかを確認し、インデックスに競合がないかどうかを確認して、コミットを避けることができます。競合がなければ、あなたはそれをツリーとして書くことができ、他の時間と同じように、そのツリーでコミットを作成することができます。 –

答えて

1

私はこの問題を解決しました。衝突検出は正常に機能しました。自動的に解決できない競合が発生した場合、コントロールはユーザーに返されました。彼は変更を加え、紛争分析が再び起こる前にそれらの変更はコミットされませんでした。このコードは、あなたが何を示していない

////////////////////////////////////////////////////////// 
// 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 
} 
関連する問題