Ruby Rugged 使用简介

1. 初始化仓库

1.1 使用路径打开存在的仓库

repo = Rugged::Repository.new('path/to/my/repository')

1.2 创建一个新的仓库

Rugged::Repository.init_at('.', :bare)

1.3 根据子目录搜寻仓库

Rugged::Repository.discover("/Users/me/projects/repo/lib/subdir/")

2. 分支操作

2.1 创建分支

repo.create_branch('branch-name')

2.2 切换到某一个分支

repo.checkout('branch-name')

2.3 查找分支

根据某个关键字查找分支:

branch_names = []
last_commits = []

repo.branches.each do |branch|
  keywords.each do |keyword|
    if branch.name.include?(keyword)
      branch_names << branch.name
      last_commits << repo.branches[branch.name].target
    end
  end
end

branch_names 用来保存符合条件的分支名字,last_commits 用来保存这些分支的最后一次提交。

2.4 获取分支

branch = repo.branches[branch_name]

3. 增加对文件的追踪

3.1 增加对单个文件的追踪

repo.index.add('./b.txt') # path or object
commit_tree = repo.index.write_tree repo
repo.index.write

相当于 git add b.txt 的操作。注意:index.write 操作会同步暂存区和工作目录。在增加或者删除对文件的追踪后必须要执行,否则执行 git status 看不到预期的效果。疑问:commit_tree = repo.index.write_tree repo 的作用是获取提交时所需要的 tree 参数?

3.2 增加对多个文件的追踪

repo.index.add_all
repo.index.write

相当于 git add -A 操作。

4. 创建 commit

author = { email: "wuzhiyu@note4code.com",
           name: "wuzhiyu",
           time: Time.now }
options = {}
options[:author] = author
options[:commiter] = author
options[:message] = "commit message here"
options[:parents] = repo.empty? ? [] : [ repo.head.target ].compact
options[:tree] = commit_tree
options[:update_ref] = 'HEAD'
Rugged::Commit.create(repo, options)

5. 分支的合并

5.1 commit 合并分析

repo.merge_analysis(last_commits[index])

返回一个包含如下 symbol 组合的数组:

symbol description
:normal A “normal” merge is possible, both HEAD and the given commit have diverged from their common ancestor. The divergent commits must be merged.
:up_to_date The given commit is reachable from HEAD, meaning HEAD is up-to-date and no merge needs to be performed.
:fastforward The given commit is a fast-forward from HEAD and no merge needs to be performed. HEAD can simply be set to the given commit.
:unborn The HEAD of the current repository is “unborn” and does not point to a valid commit. No merge can be performed, but the caller may wish to simply set HEAD to the given commit.

5.2 commit 的合并

#git fetch:
remote = Rugged::Remote.lookup(repo, "origin")
remote.connect(:fetch) do |r|
  r.download
  r.update_tips!
end

#git merge:
merge_index = repo.merge_commits(
  Rugged::Branches.lookup(repo, "master").tip,
  Rugged::Branches.lookup(repo, "origin/master").tip
)
raise "Conflict detected!" if merge_index.conflicts?
merge_commit = Rugged::Commit.create(repo, {
  parents: [
    Rugged::Branches.lookup(repo, "master").tip,
    Rugged::Branches.lookup(repo, "origin/master").tip
  ],
  tree: merge_index.write_tree(repo),
  message: 'Merged `origin/master` into `master`',
  author:    { name: "User", email: "example@test.com" },
  committer: { name: "User", email: "example@test.com" },
  update_ref: 'master'
})

上文中使用了 merge_index.conflicts? 来测试是否有冲突。但是这种冲突检测方法仅限于检测目录的冲突,也就是说只要两个分支修改了同一个文件就会报冲突,但实际上修改的内容可能并不冲突。而使用合并命令则可以针对行来检测是否冲突。

6.参考

发表评论