Last Updated: February 25, 2016
·
3.144K
· mojavelinux

Commit a new file to git using Rugged

This tip demonstrates how to use Rugged to commit a new file to git and leave behind a clean working directory.

Rugged is a library that provides Ruby API bindings for libgit2, a C implementation of the git operations. Rugged is quickly replacing grit and similar Ruby libraries because it performs operations on the git repository using direct API calls instead of calling git as a system command.

One of the first things you'll want to do when using Rugged is to commit a file programmatically. Unlike git libraries you may have used in the past, Rugged (and libgit2) requires a deeper understanding of how a commit is structured and the interplay between the git repository (i.e., the database) and the working directory.

We'll start by creating a repository without using Rugged to establish a starting point.

git_email = 'octocat@github.com'
git_name = 'The Octocat'
repo_name = 'sample-repo'

Dir.mkdir repo_name
Dir.chdir repo_name do
  File.open 'README.md', 'w' do |f|
    f.write %(# README\n\nYou will read me and be informed.)
  end
  `git init .`
  `git add README.md`
  `git commit -m "add README" --author "#{git_name} <#{git_email}>" README.md`
end

You can inspect the repository to see that it has one file and one commit.

We'll now use Rugged to remove the README.md file and replace it with a README.adoc file.

require 'rugged'

# (1)
repo = Rugged::Repository.new repo_name

# (2)
repo.checkout 'refs/heads/master'

# (3)
index = repo.index

# (4)
File.unlink File.join(repo.workdir, 'README.md')
index.remove 'README.md'

# (5)
File.open File.join(repo.workdir, 'README.adoc'), 'w' do |f|
  f.write %(= README\n\nYou will read me and be informed.)
end
index.add path: 'README.adoc',
  oid: (Rugged::Blob.from_workdir repo, 'README.adoc'),
  mode: 0100644

# (6)
commit_tree = index.write_tree repo

# (7)
index.write

# (8)
commit_author = { email: git_email, name: git_name, time: Time.now }
Rugged::Commit.create repo,
  author: commit_author,
  committer: commit_author,
  message: 'Adding README from which all shall learn',
  parents: [repo.head.target],
  tree: commit_tree,
  update_ref: 'HEAD'

Here is what this code is doing:

  • (1) Load up the repository in Rugged
  • (2) Make sure we're on the right branch (e.g., refs/heads/master)
  • (3) Retrieve a reference to the repository's index for this branch
  • (4) Remove the README.md from disk and from the repository's index
  • (5) Write the README.adoc file to disk and add it to the repository's index
  • (6) Write the changes made to the index to the git repository (i.e., the git database)
  • (7) Sync the index and the working directory (does not modify the working directory)
  • (8) Create a new commit and update HEAD to point to it

If you had a remote named 'origin' setup, you can follow the commit with a push operation:

repo.push 'origin', ['refs/heads/master']

Although this appears to be a lot of steps, once you understand the distinction between the index, the tree and the working directory, you'll appreciate the depth of control this API gives you to interact with a git repository.

NOTE: If you're not trying to keep the working directory in sync, then you can skip the steps that explicitly add and remove files as well as the call to index.write.

1 Response
Add your response

Im wondering if I can do git clonewhy would I use rugged?

over 1 year ago ·