2

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!

davoclavo
  • 1,432
  • 16
  • 19

4 Answers4

4

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)
davoclavo
  • 1,432
  • 16
  • 19
3

A simpler solution, which avoids having to manually create commit objects (And also manually create new indexes, if you wanted to add files too):

from git import Repo, Actor # GitPython
import git.exc as GitExceptions # GitPython
import os # Python Core


# Example values
respository_directory = "."
new_file_path = "MyNewFile"
action_date = str(datetime.date(2013, 1, 1))
message = "I am a commit log! See commit log run. Run! Commit log! Run!"
actor = Actor("Bob", "Bob@McTesterson.dev" )

# Open repository
try:
    repo = Repo(respository_directory)
except GitExceptions.InvalidGitRepositoryError:
    print "Error: %s isn't a git repo" % respository_directory
    sys.exit(5)

# Set some environment variables, the repo.index commit function
# pays attention to these.
os.environ["GIT_AUTHOR_DATE"] = action_date
os.environ["GIT_COMMITTER_DATE"] = action_date

# Add your new file/s
repo.index.add([new_file_path])

# Do the commit thing.
repo.index.commit(message, author=actor, committer=actor)
Aquarion
  • 591
  • 3
  • 17
3

You can set commit_date when making the commit.

r.index.commit(
    "Initial Commit",
    commit_date=datetime.date(2020, 7, 21).strftime('%Y-%m-%d %H:%M:%S')
)
chaitan94
  • 2,153
  • 1
  • 18
  • 19
1

I am also using specified date/time for committing purpose. In my case after a long research I have figured out, that you have to give the datetime not really in ISO format as GitPython suggests you should, nor in timestamp format. It is actually making delusion because of its own "parsing" that is should be a standard python format.

Nope. You have to give it in the format that git itself would understand.

For example:

# commit_date is your specified date in datetime format
commit_date_as_text = commit_date.strftime('%Y-%m-%d %H:%M:%S %z')
git_repository.index.commit(commit_message, author=commit_author, commit_date=commit_date_as_text)

List of accepted formats you can find for example in another topic on StackOverflow.

Jacek Krawczyk
  • 2,083
  • 1
  • 19
  • 25