4

I am planning to use Rugged for programmatically accessing Git repositories.

I need to find out the files changed in a specific commit.

Commit object provides the following, according to the documentation.

  • message
  • time
  • author
  • tree
  • parents

I tried the "tree" route, but could not succeed.

I see a similar question asked in SO, in relation to Grit. But, I would like to use Rugged.

In ruby/grit, how do I get a list of files changed in a specific commit?

Community
  • 1
  • 1
Geordee Naliyath
  • 1,799
  • 17
  • 28
  • I was alternating between ruby-git and rugged. Got a nice solution using ruby-git. Keeping the question open for others who may walk down this path. – Geordee Naliyath Feb 17 '15 at 17:52

3 Answers3

3

You can use Rugged::Commit#diff to get the changes between the commit and its first parent or another Rugged::Commit or Rugged::Tree.

  • I went that route, since I am using "g.diff(commit, commit.parents.first).stats[:files].keys" to find it using ruby-git. I did not have much success though. – Geordee Naliyath Feb 18 '15 at 10:26
  • `Rugged::Commit#diff` returns a `Rugged::Diff` object. you can get a list of changed objects with the `Rugged::Diff#deltas` method, which will return a list of `Rugged::Diff::Delta` objects. Each delta object represents a changed file. See http://www.rubydoc.info/gems/rugged/Rugged/Diff/Delta – Arthur Schreiber Feb 18 '15 at 14:17
  • I was quite close. Earlier, I was iterating through the Rugged::Diff and trying to run each_delta on the patch object. Unfortunately I named my variable "diffs" and was looking for delta method in the "diff" variable. Thanks! – Geordee Naliyath Feb 18 '15 at 18:18
2

Here is a snippet based on Arthur's answer.

require 'rugged'

paths = [];

repo = Rugged::Repository.new('/Users/geordee/Code/HasMenu/data')

walker = Rugged::Walker.new(repo)

walker.sorting(Rugged::SORT_TOPO | Rugged::SORT_REVERSE)
walker.push(repo.head.target)
walker.each do |commit|
  # skip merges
  next if commit.parents.count != 1

  diffs = commit.parents[0].diff(commit)
  diffs.each_delta do |delta|
    paths += [delta.old_file[:path], delta.new_file[:path]]
  end

end

puts paths

This probably skips the first commit.

Geordee Naliyath
  • 1,799
  • 17
  • 28
1

A simpler way to get all files in specific commit based on HEAD.

require "rugged"

repo = Rugged::Repository.new('.')
commit = repo.head.target

paths = commit.diff(commit.parents.first).deltas.map { |d| [d.old_file[:path], d.new_file[:path]] }.flatten.uniq