私はgit
でプロジェクトを統合したプロジェクトに取り組んでいます。統合の目的で、私はgo-git
ライブラリを使用しています。私の質問は、プログラムで2つのブランチの共通の祖先を見つける方法です。私はこの機能を実装したい。 go-git
のように見え、他のgoライブラリはそのような機能を提供していません。プログラムで2つのブランチの共通祖先を見つける方法
1
A
答えて
0
は、小さなプログラムはgit merge-base --all
package main
import (
"fmt"
"os"
"gopkg.in/src-d/go-git.v4"
. "gopkg.in/src-d/go-git.v4/_examples"
"gopkg.in/src-d/go-git.v4/plumbing"
"gopkg.in/src-d/go-git.v4/plumbing/object"
"gopkg.in/src-d/go-git.v4/plumbing/storer"
)
// store h in set, s, handling nil s if necessary. Return new set.
func store(s map[plumbing.Hash]bool, h plumbing.Hash) map[plumbing.Hash]bool {
if s == nil {
s = make(map[plumbing.Hash]bool)
}
s[h] = true
return s
}
// mergeBase finds best common ancestors between two commits to use in a
// three-way merge. One common ancestor is better than another common ancestor
// if the latter is an ancestor of the former. A common ancestor that does not
// have any better common ancestor is a best common ancestor, i.e. a merge base.
// Note that there can be more than one merge base for a pair of commits.
func mergeBase(s storer.EncodedObjectStorer, a, b plumbing.Hash) ([]plumbing.Hash, error) {
commitA, err := object.GetCommit(s, a)
if err != nil {
return nil, err
}
commitB, err := object.GetCommit(s, b)
if err != nil {
return nil, err
}
// Mapping of direct descendants of each commit we visit
desc := make(map[plumbing.Hash]map[plumbing.Hash]bool)
// Set of commits reachable from a
reachableFromA := make(map[plumbing.Hash]bool)
// Walk commits reachable from A
err = object.NewCommitPreorderIter(commitA, nil, nil).ForEach(func(c *object.Commit) error {
reachableFromA[c.Hash] = true
for _, h := range c.ParentHashes {
desc[h] = store(desc[h], c.Hash)
}
return nil
})
if err != nil {
return nil, err
}
// Set of common commits between a and b
common := make(map[plumbing.Hash]bool)
// Walk commits reachable from B
err = object.NewCommitPreorderIter(commitB, nil, nil).ForEach(func(c *object.Commit) error {
if reachableFromA[c.Hash] {
common[c.Hash] = true
}
for _, h := range c.ParentHashes {
desc[h] = store(desc[h], c.Hash)
}
return nil
})
if err != nil {
return nil, err
}
best := make(map[plumbing.Hash]bool)
// Trim down the set of common commits to only those that are best
for h := range common {
best[h] = true
for child := range desc[h] {
if common[child] {
// there is a descendant to h that is common to both a and b. h is not in best.
delete(best, h)
break
}
}
}
var result []plumbing.Hash
for h := range best {
result = append(result, h)
}
return result, nil
}
// Open an existing repository in a specific folder.
func main() {
CheckArgs("<path> <commitA> <commitB>")
path := os.Args[1]
a := plumbing.NewHash(os.Args[2])
b := plumbing.NewHash(os.Args[3])
r, err := git.PlainOpen(path)
CheckIfError(err)
bases, err := mergeBase(r.Storer, a, b)
CheckIfError(err)
for _, b := range bases {
fmt.Println(b)
}
}
+0
ありがとう@orirawlings –
1
は、コマンドの結果を使用することができます:ここで
git merge-base branch1 branch2
+0
このコマンドをgolangに実装したいと思います。 –
+0
おそらくhttps://github.com/libgit2/git2goに見てください – Philippe
関連する問題
- 1. gitの:どのように私は2つのブランチの共通の先祖を見つけるのですか...すでに2つのgitのブランチの共通の祖先を見つけるために
- 2. ルートを参照することなく、2つのツリーノードの共通の祖先を見つけますか?
- 3. ネストされたセット内の最も低い共通祖先を見つける
- 4. オブジェクトの祖先の型を見つける方法は?
- 5. Neo4j最低共通祖先ノードが見つかりません
- 6. 2-3ツリーの正しい祖先を見つける
- 7. 分裂器で先祖を見つけるのを避ける方法cssContainingText locator
- 8. 共通の先祖クラス
- 9. 2つの画像で共通のものを見つける
- 10. 2つのフォルダ間で共通のファイルを見つける
- 11. 2つの値の共通の因数を見つける
- 12. Scala最低共通祖先
- 13. NetworkXを持つすべての最低共通祖先
- 14. 2つのリストの共通項目を見つける
- 15. ツリー内で最も共通の祖先を見つける際にエラーが発生しました。
- 16. Mercurialとbzrのマージベースアナログ(マージのために共通の祖先を見つけるために)?
- 17. プロパティ配列で共通の値を見つける方法
- 18. バイナリツリーの最初の共通祖先
- 19. 2つのpython-listsで共通の属性を持つオブジェクトを見つけるのに効率的な方法
- 20. 共通の祖先を持つ制約のあるレコードのセットをコピーする
- 21. 特定の属性を持つ要素の子である祖先を見つける方法は?
- 22. リスト内の共通要素を見つける方法
- 23. Pythonでループのない2つのタプルリストの共通タプルを見つける
- 24. 2つのURLの間で共通のパターンを見つけるには
- 25. PHPで2つの数値の共通の除数を見つけるには?
- 26. matlabで2つの条件を満たす共通のインデックスを見つける
- 27. 2つのノード間の祖先
- 28. CSSクラスを含む祖先ノードを見つけるXPath
- 29. Prologでマップの2つのポイント間で共通の駅を見つける方法はありますか?
- 30. Java:2つの文字列で共通文字を見つける
https://github.com/src-d/の行動を模倣
go-git
を使用していますgo-git/issues/679 – orirawlings