Repository navigation
Open
Description
Been trying to implement signing of commits in a project we use.
I have sort of gotten it to work but the implementation between a none signed commit and signed commit differs a lot and i would like it to become much easier so the code in the project i use gets cleaner.
Basically this is how we implemented none signed today, it works for a newly created bare repo also.
oid = repo.write("This is a blob.", :blob)
index = repo.index
index.read_tree(repo.head.target.tree)
index.add(:path => "README.md", :oid => oid, :mode => 0100644)
options = {}
options[:tree] = index.write_tree(repo)
options[:author] = { :email => "testuser@github.com", :name => 'Test Author', :time => Time.now }
options[:committer] = { :email => "testuser@github.com", :name => 'Test Author', :time => Time.now }
options[:message] ||= "Making a commit via Rugged!"
options[:parents] = repo.empty? ? [] : [ repo.head.target ].compact
options[:update_ref] = 'HEAD'
@commitref = Rugged::Commit.create(repo, options)
index.writeBut to make signed commits in a new bare repo the first part is the same with options but alot after differs.
oid = repo.write("This is a blob.", :blob)
index = repo.index
index.read_tree(repo.head.target.tree)
index.add(:path => "README.md", :oid => oid, :mode => 0100644)
options = {}
options[:tree] = index.write_tree(repo)
options[:author] = { :email => "testuser@github.com", :name => 'Test Author', :time => Time.now }
options[:committer] = { :email => "testuser@github.com", :name => 'Test Author', :time => Time.now }
options[:message] ||= "Making a commit via Rugged!"
options[:parents] = repo.empty? ? [] : [ repo.head.target ].compact
options[:update_ref] = 'HEAD'
# Create a string of the contents to be commited.
content = Rugged::Commit.create_to_s(repo, options)
# Sign the string.
crypto = GPGME::Crypto.new(armor: true)
signature = crypto.detach_sign(content, signers: @cfg.sign_key).to_s.strip
# Create a commit using the string and signature.
@commitref = Rugged::Commit.create_with_signature(repo, content, signature, 'gpgsig')
# After doing this create_with_signature calling for index.write does not work.
# and i have to do this repo references else i cant see any commits when i do git log --show-signature
# Check if HEAD exists and handle accordingly
if repo.references.exist?("HEAD") && !repo.head_unborn?
# HEAD exists and points to a real branch
repo.references.update(repo.head.name, @commitref)
else
# HEAD doesn't exist or is unborn - create default branch
repo.references.create("refs/heads/master", @commitref)
endI would like the implementation of signed commits to be as easy as doing a normal commit just that i have to specify the key i want to sign with.
e.g
# Just want a function i can call for as easy as Commit.create that signs my commits and update the reference on disk.
Rugged::Commit.commit_with_signature(repo, options, signature)Metadata
Metadata
Assignees
Labels
No labels
Activity
Sparc0 commentedon Oct 7, 2025
Anyone?
carlosmn commentedon Jun 28, 2026
I don't think it can be done "easy" like you say. How would the library know how to sign? How would it ask for the password, or the myriad of other possibilities for signing data? The best it could do is execute some helper program, but we don't do that here and you would have to have told the library exactly what you want to run in each instance, which provides no advantage.
One thing you could build is a method that takes a callback/proc that gets fed the content to sign, and then the caller can figure out what their environment needs, and then you return the resulting signature to use. But you can build that yourself if that's what you need, without it having to exist within this library.