rugged は libgit2 を ruby にバインドした gem です。
gitの細かい操作が出来て便利。
自分が前に使っていた時のメモです。(1年前のなのでちょっと古いかも)
colorize は見栄えを良くするために使っています。
git clone
require 'rugged'
url = 'https://github.com/siman-man/rugged-examples'
local_path = File.expand_path('repos/rugged-examples', Dir.pwd)
repo = Rugged::Repository.clone_at(url, local_path)
private なリポジトリを取ってくる時は access_token を発行して、credentials 情報を追加してあげる。
require 'rugged'
url = 'https://github.com/siman-man/rugged-examples'
local_path = File.expand_path('repos/rugged-examples', Dir.pwd)
credentials = Rugged::Credentials::UserPassword.new(
username: "access_token",
password: ""
)
repo = Rugged::Repository.clone_at(url, local_path, credentials: credentials)
git reflog
require 'colorize'
require 'rugged'
repo = Rugged::Repository.new('.')
ref = repo.head
ref.log.reverse_each do |entry|
sha = entry[:id_new]
message = entry[:message]
committer = entry[:committer]
author = committer[:name]
email = committer[:email]
time = committer[:time]
puts <<-GITLOG
# {"commit\t#{sha}".yellow}
Author:\t#{author} <#{email}>
Date:\t#{time}"
#{message}"
GITLOG
end
git branch
require 'colorize'
require 'rugged'
repo = Rugged::Repository.new('.')
repo.branches.each do |branch|
name = branch.name
remote_name = branch.remote_name
next if name.include?('/')
if branch.head?
puts "* #{name.green}"
else
puts " #{name}"
end
end
git branch [name]
ブランチの作成
require 'rugged'
repo = Rugged::Repository.new('.')
repo.create_branch('test')
git log
require 'colorize'
require 'rugged'
repo = Rugged::Repository.new('.')
repo.walk(repo.last_commit).take(5).each do |entry|
sha = entry.oid
message = entry.message.chomp
committer = entry.author
author = committer[:name]
email = committer[:email]
time = committer[:time]
puts "commit #{sha}".yellow
puts "Author:\t#{author} <#{email}>"
puts "Date:\t#{time}"
puts ""
puts "#{message}"
puts ""
end
git ls-tree
require 'rugged'
repo = Rugged::Repository.new('.')
ref = repo.head
commit = ref.target
tree = commit.tree
tree.each do |obj|
puts "%06o #{obj[:type]} #{obj[:oid]}\t#{obj[:name]}" % [obj[:filemode]]
end
git diff
require 'colorize'
require 'rugged'
def color_diff_message(message)
message.split("\n").map {|line|
case line
when /^\+/
line.green
when /^\-/
line.red
when /^@@.*@@$/
line.cyan
else
line
end
}.join("\n")
end
repo = Rugged::Repository.new('.')
diff = repo.diff_workdir(repo.last_commit)
diff.each_patch do |patch|
puts color_diff_message(patch.to_s)
end
git status [WIP]
結講実装が面倒
require 'rugged'
require 'colorize'
# TODO: not yet implemented
repo = Rugged::Repository.new('.')
repo_status = Hash.new{|h,k| h[k] = []}
index_files = []
worktree_files = []
repo.status {|file, status_data|
repo_status[status_data.first] << file
status = status_data.first
if %i(index_new index_modified index_deleted).include?(status_data.first)
index_files << [file, status]
elsif %i(worktree_new worktree_modified worktree_deleted).include?(status_data.first)
worktree_files << [file, status]
end
}
puts "On branch master"
puts "Your branch is up-to-date with 'origin/master'."
puts ' Changes to be committed:'
puts ' (use "git reset HEAD <file>..." to unstage)'
puts ''
index_files.each do |file, status|
status = status.to_s.gsub('index_', '')
puts "\t#{status} file: #{file}".green
end
puts ''
puts 'Untracked files:'
puts ' (use "git add <file>..." to include in what will be committed)'
puts ''
worktree_files.each do |file, status|
status = status.to_s.gsub('worktree_', '')
puts "\t#{file}".red
end
puts ''
一番最初のコミットを取得
require 'rugged'
repo = Rugged::Repository.new('.')
first_commit = repo.walk(repo.last_commit).to_a.last
puts first_commit.oid
puts first_commit.message
一番最後のコミットを取得
Repository#last_commit
で取得可能
require 'rugged'
repo = Rugged::Repository.new('.')
commit = repo.last_commit
puts commit.oid
puts commit.message
指定した範囲のコミットオブジェクトを取得
require 'rugged'
repo = Rugged::Repository.new('.')
def range_log(repo, from, to)
logs = []
commits = repo.walk(from)
commits.each do |commit|
break if to.oid == commit.oid
logs << commit
end
if commits.size == logs.size
raise 'Object not found' if commits.size == logs.size
else
logs
end
end
commits = repo.walk(repo.last_commit).to_a
logs = range_log(repo, commits[0], commits[5])
p logs.size
最新コミットからある特定の時間までのコミットを取得
require 'rugged'
repo = Rugged::Repository.new('.')
def get_timerange_log(repo, time)
repo.walk(repo.last_commit).take_while do |commit|
commit.time > time
end
end
# 1 hour's commits
hour_logs = get_timerange_log(repo, Time.now - 3600)
# 1 day's commits
day_logs = get_timerange_log(repo, Time.now - 3600 * 24)
# 1 week's commits
week_logs = get_timerange_log(repo, Time.now - 3600 * 24 * 7)
puts "#{hour_logs.size} commits 1 hour ago"
puts "#{day_logs.size} commits 1 day ago"
puts "#{week_logs.size} commits 1 week ago"
ファイルの中身を閲覧
git cat-file -p <object_id>
に相当するやつ、事前に対象のobject_idが判明している場合は Rugged::Blob.lookup(repo, object_id)
が良さそう
require 'rugged'
repo = Rugged::Repository.new('.')
revision = repo.last_commit.oid
path = 'Gemfile'
blob = repo.blob_at(revision, path)
puts blob.text
puts ""
puts blob.content
Blob#content
でも同様の処理が可能、#text
と #content
には引数が渡せて、#text
の方では「最大n行まで」、#content
では「最大n bytes」までの取得を行う操作が可能
ブランチ属性でフィルタリング
ローカルブランチとリモートブランチのフィルタリングが可能
require 'colorize'
require 'rugged'
repo = Rugged::Repository.new('.')
repo.branches.each(:local) do |local_branch|
puts local_branch.name
end
repo.branches.each(:remote) do |remote_branch|
puts remote_branch.name
end
puts "\nlocal branche list"
repo.branches.each_name(:local) do |name|
puts " #{name}"
end
puts "\nremote branch list"
repo.branches.each_name(:remote) do |name|
puts " #{name}"
end
ブランチを削除する
強制削除
require 'rugged'
repo = Rugged::Repository.new('.')
branch_name = 'sample_branch'
# git branch -D branch_name
repo.branches.delete(branch_name)
ブランチオブジェクトを取得する
BranchCollection#[]
にブランチ名を渡して上げると取れる
require 'rugged'
repo = Rugged::Repository.new('.')
branch_name = 'master'
branches = repo.branches
branch = branches[branch_name]
puts branch.name
ブランチが存在するかどうかを調べる
BranchCollection#exist
と BranchCollection#exists
が使える
require 'rugged'
repo = Rugged::Repository.new('.')
branches = repo.branches
p branches.exist?('hoge') #=> false
p branches.exist?('master') #=> true
p branches.exists?('hoge') #=> false
p branches.exists?('master') #=> true
コミット情報の出力
git log コマンドに parent_id と Committer 情報を足したぐらい
require 'rugged'
require 'colorize'
repo = Rugged::Repository.new('.')
commit = repo.last_commit
author = commit.author
committer = commit.committer
puts <<-COMMIT_LOG
parents: #{commit.parent_ids.join(', ').blue}
commit #{commit.oid.yellow}
Author: #{author[:name]} <#{author[:email]}>
Committer: #{committer[:name]} <#{committer[:email]}>
Date: #{committer[:time]}
#{commit.message}
COMMIT_LOG
最新コミットのファイル一覧表示
最後の表示部分は puts [root, entry[:name]].join
でもOK
require 'rugged'
require 'pathname'
repo = Rugged::Repository.new('.')
repo.last_commit.tree.walk_blobs do |root, entry|
puts Pathname.new(root).join(entry[:name])
end