Search code examples
gitgroovyegitjgit

Commit/Log only when files change


I'm trying to use jgit to track and commit changes in files, but I am seeing a strange behavior with the CommitCommand if the file content actually does not change its logging a actual commit in the repo.

To reproduce the my issue run this test case code 3 times. The first time the new file get committed as expected, but why are the other two executions being logged knowing that the file is the same?

Am I missing something here?

Test case output:

# groovy -cp org.eclipse.jgit-3.4.0.201406110918-r.jar testcase.groovy
Repo Not found, creating it!
Saving String to file: repo\test.txt
Added file(s): 1
reflogs size: 1

# groovy -cp org.eclipse.jgit-3.4.0.201406110918-r.jar testcase.groovy
Saving String to file: repo\test.txt
Added file(s): 1
reflogs size: 2

# groovy -cp org.eclipse.jgit-3.4.0.201406110918-r.jar testcase.groovy
Saving String to file: repo\test.txt
Added file(s): 1
reflogs size: 3

# git log
-------
commit b22c369dfeb225254687cccfbf244459395a716f
Author: TestUser <xx@xx>
Date:   Fri Jun 27 01:05:27 2014 +0200

    CMessage

commit 0d8bb99d80c561e7bbc3504fdd9bc7da99bb82e4
Author: TestUser <xx@xx>
Date:   Fri Jun 27 01:04:13 2014 +0200

    CMessage

commit 2195dfe7d5536c88eb3d4e953967463bb699c9b2
Author: TestUser <xx@xx>
Date:   Fri Jun 27 01:04:10 2014 +0200

    CMessage

Test code:

import org.eclipse.jgit.*
import org.eclipse.jgit.api.*
import org.eclipse.jgit.errors.*
import org.eclipse.jgit.lib.*
import org.eclipse.jgit.dircache.*
import java.nio.file.*

Git repOpen(Path wDir){
  Git git
  try{
    git = Git.open(wDir.toFile())
  }catch(RepositoryNotFoundException e){
    println "Repo Not found, creating it!"
    git = repCreate(wDir)
  }catch(Exception e){
    println "Error openning Repo: ${e}"
  }
  return git
}
Git repCreate(Path wDir){
  Git git
  try{
    InitCommand initCommand = Git.init()
    initCommand.setDirectory(wDir.toFile())
    git = initCommand.call()

    // Set git repo options
    StoredConfig conf = git.getRepository().getConfig()
    conf.setBoolean("core", null, "autocrlf", true)
    conf.setBoolean("core", null, "filemode", false)
    conf.save()

  }catch(Exception e){
    println "Error creating Repo: ${e}"
  }
  return git
}
void saveStringToFile(Path file, String data){
  println "Saving String to file: ${file}"
  new FileWriter(file.toFile()).withWriter { writer -> writer.write(data) }
}


//  DO THE WORK
String dummyFileContent = "DummyContent:\nLine\nLine2\nLine3"

Path repoPath = Paths.get('repo')
Git g = repOpen(repoPath)

Path file = repoPath.resolve(Paths.get('test.txt'))
saveStringToFile(file, dummyFileContent)

DirCache dc = g.add().addFilepattern('.').call()
println "Added file(s): $dc.entryCount"

g.commit().setAll(true).setMessage('CMessage').call()
println "reflogs size: ${g.reflog().call().size()}"

Solution

  • Calling a CommitCommand will always create a commit, regardless of whether there are any changes or not. In your case, the second and third commit will be empty, i.e. it does not reference any files.

    To create a commit only if the work directory contains changes you can check its status first like so:

    if( !g.status().call().isClean() ) {
      g.commit()...
    }