I clone a repository as bare on my local disk using JGit. Now, I need to read the contents of a file at any given commit id (SHA1). How do I do this ?
Asked
Active
Viewed 2,781 times
2 Answers
3
The comment of Rüdiger Herrmann in this answer contains the relevant hints; but to make it easier for the friends of copy & paste solutions here my complete self-contained example code of a junit test that creates a revision of a file and then retrieves the contents of this revision. Works with jGit 4.2.0.
@Test
public void test() throws IOException, GitAPIException
{
//
// init the git repository in a temporary directory
//
File repoDir = Files.createTempDirectory("jgit-test").toFile();
Git git = Git.init().setDirectory(repoDir).call();
//
// add file with simple text content
//
String testFileName = "testFile.txt";
File testFile = new File(repoDir, testFileName);
writeContent(testFile, "initial content");
git.add().addFilepattern(testFileName).call();
RevCommit firstCommit = git.commit().setMessage("initial commit").call();
//
// given the "firstCommit": use its "tree" and
// localize the test file by its name with the help of a tree parser
//
Repository repository = git.getRepository();
try (ObjectReader reader = repository.newObjectReader())
{
CanonicalTreeParser treeParser = new CanonicalTreeParser(null, reader, firstCommit.getTree());
boolean haveFile = treeParser.findFile(testFileName);
assertTrue("test file in commit", haveFile);
assertEquals(testFileName, treeParser.getEntryPathString());
ObjectId objectForInitialVersionOfFile = treeParser.getEntryObjectId();
// now we have the object id of the file in the commit:
// open and read it from the reader
ObjectLoader oLoader = reader.open(objectForInitialVersionOfFile);
ByteArrayOutputStream contentToBytes = new ByteArrayOutputStream();
oLoader.copyTo(contentToBytes);
assertEquals("initial content", new String(contentToBytes.toByteArray(), "utf-8"));
}
git.close();
}
// simple helper to keep the main code shorter
private void writeContent(File testFile, String content) throws IOException
{
try (OutputStreamWriter wr = new OutputStreamWriter(new FileOutputStream(testFile), Charset.forName("utf-8")))
{
wr.append(content);
}
}
Edit to add: another, probably better example is at https://github.com/centic9/jgit-cookbook/blob/master/src/main/java/org/dstadler/jgit/api/ReadFileFromCommit.java

Roman
- 4,922
- 3
- 22
- 31

Clemens Klein-Robbenhaar
- 3,457
- 1
- 18
- 27
-
2Good idea. To focus on demonstrating the ObjectLoader the snippet could be simplified: `setBare(false)` is the default, no need to re-open the repo - re-use `initialized`, `firstCommit` is returned from `ci.call()`, no need for a second commit. BTW the temporary folder is not deleted. – Rüdiger Herrmann Mar 21 '16 at 16:00
-
Thanks for the suggested simplifications; these should be integrated now. I did not know that one could get at the repository via `Repository repository = git.getRepository()` - good to find this out. And yes, the temp folder is not deleted, I just left it as this is not really a unit test to be run all the time, just demo code. – Clemens Klein-Robbenhaar Mar 22 '16 at 11:32
0
By using this. Iterable<RevCommit> gitLog = gitRepo.log().call();
you can get all the commit hash from that object.

code-red
- 306
- 3
- 12
-
Yes. I got the commit hash which I wanted. But How do I read the contents of a particular file in the tree at this hash ? – Gaurav Shah Jun 18 '12 at 13:42
-
you need to checkout that hash and gets the contents of the files. in terminal you can do `git checkout
`. – code-red Jun 19 '12 at 02:56 -
ow... I missed that word.. so it is a bare repo. I think you need to clone it first to get the files. bare repo is for information of the repository only. – code-red Jun 20 '12 at 08:45
-
I think you can't on a bare repo, but did you try branching from the commit? – Vince Jun 20 '12 at 09:33
-
Why do you even want to do this operation on a bare repo? I kept in mind that bare repo is like a server you change the content only through an identified client (i.e. a non-bare repo). So I think it is just not what it is used for. If you want to read an old version of a file, then you probably work on this file [using a non-bare repo]. Does this suggestion make sense? – Vince Jun 20 '12 at 09:41
-
Well, I am writing a tool which needs to sync repos in order to read files inside the repos. If I don't sync them as bare, we have a possible threat of the repos getting dirty with local changes. This tool is never going to change anything, it will always read. – Gaurav Shah Jun 26 '12 at 07:53
-
As you say it yourself "we have a possible threat of the repos getting dirty with local changes. This tool is never going to change anything, it will always read". If the threat is change and your tool is not changing anything, then there is no threat any more! – Vince Aug 29 '12 at 14:47
-
2@GauravShah Once you have a SHA-1 that points to a Git object, you can use `ObjectReader` and `ObjectLoader` to reveal its contents: `ObjectReader objectReader = repository.newObjectReader(); ObjectLoader objectLoader = objectReader.open( objectId ); objectLoader.openStream();` (don't forget to release the ObjectReader when done) See also [this article](http://www.codeaffine.com/2014/10/20/git-internals/) for more details. – Rüdiger Herrmann Oct 31 '14 at 10:58