Some notes about libgit2/rugged

violet posted @ Nov 06, 2015 02:42:44 PM in 笔记 with tags ruby Rugged , 30534 阅读

I learned libgit2/rugged when I involved in a project which is to analysis a repository. I found it's a little hard to use Rugged to do the basic things, e.g. `git pull`, `git push`, etc. This is the purpose that I want to add some notes here. In case of someday there's someone likes me who encounter into these kinds of stuff. ლ(╹◡╹ლ)

- find a repository

repo ='path/to/my/repository')

repo ="/Users/me/projects/repo/lib/subdir/")


- clone a repository

credentials =
options = {}
options.merge!(:credentials => credentials) if credentials.exist?
Rugged::Repository.clone_at(url, target_dir, options)
# url may like this for github:
# username for github in credentials should be `git`
# options will pass your identity to github. Even you just clone a public repository.


- fetch from remote repo

refspecs = [ "#{}:#{}" ]
options = {}
options.merge!(credentials) if credentials
results = repo.remote.fetch(refspecs, options)
results.merge!(new_target: repo.remote_ref.target_id)
# Returns hash with the result of the action together with hash containing statistics
# for the fetch operation: :total_objects=>0, :indexed_objects=>6, :received_bytes=>0,
# received_objects=>0, :local_objects=>0, :total_deltas=>0, :indexed_deltas=>0.
# :new_target=>"iekcicie493kd049930202" will be added if some new data were fetched.
# If the action fails the hash will contain only :error=>"some error message"

- merge commits

This method is from this question

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: "" },
  committer: { name: "User", email: "" },
  update_ref: 'master'


- pull from remote repo

Pull operation could be achieved by fetch + merge

- rebase

As it's said, rebase hasn't been implemented in libgit2. So we may just walk through the commit and update the reference to do rebase operation.

- create commit

index = repo.index
oid = Rugged::Blob.from_workdir repo, relative_path
index.add(:path => relative_path, :oid => oid, :mode => 0100644)
# This step hasn't been provided on github page, but this is necessary.

options = {}
options[:tree] = index.write_tree(repo)
options[:author] = { :email => "" :name => "XXX", :time => }
options[:committer] = { :email => "", :name => "XXX", :time => }
options[:message] ||= commit_info
options[:parents] = repo.empty? ? [] : [ ].compact
options[:update_ref] = 'HEAD'

Rugged::Commit.create(repo, options)


- create a branch

repo.create_branch branch_name


- checkout a branch

repo.checkout branch_name


- push to remote repo

refspecs = ["refs/heads/#{branch_name}"]
options = {}
options.merge!(credentials: credentials) if credentials.exist?
repo.remotes.push refspecs, optionsrepo.remotes.clear_refspecs
refspecs = ["refs/heads/#{branch_name}"]
options = {}
options.merge!(credentials: credentials) if credentials.exist?
repo.remotes.push refspecs, options

# According to doc, it also provide repo.push operation. But it will call remote.push. And I'm not sure what exact parameter to the function(tooooooo complex).
So I recommend use Rugged::Remote.push.


- given tree and path of a file and find the oid of the file

found = nil
tree.walk(:postorder) {|root, entry| found = entry if path.eql? "#{root}#{entry[:name]}" }

# I just find it's easy to use oid of a file to locate the file, but it's not easy to do it oppositely.



登录 *

loading captcha image...
or Ctrl+Enter