Search code examples
pythongitpython

How can I specify the committed_date of a Commit using GitPython?


I would like to commit a file with a custom date.

So far I've created a Commit object, but I don't understand how to bind it to a repo.

from git import *
repo = Repo('path/to/repo')
comm = Commit(repo=repo, binsha=repo.head.commit.binsha, tree=repo.index.write_tree(), message='Test Message', committed_date=1357020000)

Thanks!


Solution

  • Well I found the solution.

    I wasn't aware, but I had to provide all the parameters otherwise the Commit object would throw a BadObject exception when trying to serialize it.

    from git import *
    from time import (time, altzone)
    import datetime
    from cStringIO import StringIO
    from gitdb import IStream
    
    repo = Repo('path/to/repo')
    
    message = 'Commit message'
    
    tree = repo.index.write_tree()
    parents = [ repo.head.commit ]
    
    # Committer and Author
    cr = repo.config_reader()
    committer = Actor.committer(cr)
    author = Actor.author(cr)
    
    # Custom Date
    time = int(datetime.date(2013, 1, 1).strftime('%s'))
    offset = altzone
    author_time, author_offset = time, offset
    committer_time, committer_offset = time, offset
    
    # UTF-8 Default
    conf_encoding = 'UTF-8'
    
    comm = Commit(repo, Commit.NULL_BIN_SHA, tree, 
          author, author_time, author_offset, 
          committer, committer_time, committer_offset,
          message, parents, conf_encoding)
    

    After creating the commit object, a proper SHA had to be placed, I didn't have a clue how this was done, but a little bit of research in the guts of GitPython source code got me the answer.

    stream = StringIO()
    new_commit._serialize(stream)
    streamlen = stream.tell()
    stream.seek(0)
    
    istream = repo.odb.store(IStream(Commit.type, streamlen, stream))
    new_commit.binsha = istream.binsha
    

    Then set the commit as the HEAD commit

    repo.head.set_commit(new_commit, logmsg="commit: %s" % message)