我正在研究一個項目,其中我的項目集成了git
。爲了整合目的,我使用了go-git
庫。我的問題是如何以編程方式找到兩個分支的共同祖先?我想實現這個功能。看起來像go-git
和其他去庫不提供這樣的功能。如何以編程方式查找兩個分支的共同祖先
1
A
回答
0
下面是使用go-git
模仿的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. 沒有共同祖先的分支
- 3. 如何查找二叉樹中節點的第一個共同祖先?
- 4. python最低共同祖先
- 5. 我如何找到共同的祖先來rebase?
- 6. 如何找到一棵樹的最低共同祖先?
- 7. 如何以編程方式查找javac.exe?
- 8. 如何查找類型類的祖先?
- 9. 在neo4j中查找最低共同祖先(LCA)
- 10. 使用.NET反射找到一個共同的祖先類
- 11. iPhone以編程方式查找ios支持的圖像格式
- 12. 如何以編程方式查找EJB的JNDI查找名稱?
- 13. 以編程方式刪除TFS分支
- 14. EXTSJS:treepanel以編程方式移動分支
- 15. 分支合併到主幹不共享祖先
- 16. 如何檢查一個分支是否是Git中的另一個分支的祖先
- 17. 如何以編程方式查找加載的共享庫的版本?
- 18. 從一組xpath中找到共同的祖先?
- 19. 如何以編程方式查找文件的編碼?
- 20. 查找XML節點集的最低公共祖先
- 21. 有沒有更好的方法找到最低的共同祖先?
- 22. 以編程方式查找設備是否支持GPS?
- 23. 如何在git merge中強制共同的祖先?
- 24. Linq to Sql - 查找祖先的分層查詢
- 25. 隨着Mercurial,你如何記錄與跨分支祖先的分支?
- 26. 以編程方式查找地區
- 27. 以編程方式查找GridView行
- 28. 如何以編程方式在黑莓上查找方向?
- 29. Google Datastore祖先查詢每個祖先每秒寫一個
- 30. 如何以編程方式區分兩種不同的蘋果手錶?
行爲小程序https://github.com/src-d/ go-git/issues/679 – orirawlings