Commits

type commit

Commit objects link the state of the tree with a description. Commits contain a description of the author, commit author and a message about the commit. They also contain state information about the current tree and links to any parent commits. Commits that have more then one parent are considered to be merges.

Creating

function (make-commit tree-or-oid message &key (update-ref "HEAD") author committer parents repository)

Create a new commit from the tree with the OID specified and MESSAGE. Optional :UPDATE-REF is the name of the reference that will be updated to point to this commit. The default value "HEAD" will updote the head of the current branch. If it's value is NULL then no reference will be updated. :AUTHOR is an optional instance of a GIT-SIGNATURE that details the commit author. :COMMITTER is an optional instance of a GIT-SIGNATURE the details the committer. :PARENTS is an optional list of parent commits sha1 hashes.

Accessing

There are a few ways to find commits in the repository, the easiest is to find a commit when we know the SHA-1 has. In that case the process is as follows:

GIT> (get-object 'commit "15b8410814ec05d63b85c5e4b735dcdc77719a08"
                 (open-repository #p"/home/russell/projects/ecl/"))
#<COMMIT 15B8410814EC05D63B85C5E4B735DCDC77719A08 {10060B27A3}>

To get access to a single reference.

GIT> (get-object 'reference "refs/heads/master"
                 (open-repository "/home/russell/projects/ecl/"))
#<REFERENCE refs/heads/master {1006F13CB3}>

However to get from a reference to a commit is easy using the TARGET method.

GIT> (target (get-object 'reference "refs/heads/master"
                         (open-repository "/home/russell/projects/ecl/")))
#<COMMIT E92F8C418F626A5041FC242C0FB1CEB1BEC4D61B {10071DE5B3}>

In this case we ended up with a commit, however a reference can refer to any object in the git database, so tags, blobs and trees are also possible.

Now in normal use you do not see references to blobs or trees very frequently, but references to tags are more common.

So in normal code you have to check for that and act accordingly.

method (get-object (class commit) (id/name T) (repository T))

macro (bind-git-commits (bindings repository-or-odb) &body body)

Lookup commits specified in the bindings. The bindings syntax is similar to the LET syntax except instead of needing to specify an initial form key arguments are used. Atleast one key arguments SHA or HEAD must be specified. SHA is a hash of the commit. HEAD is a full ref path.

method (list-objects (class commit) (repository T) &key test test-not)

Specializers:
((eql :oid) repository)
(remote common-lisp:t)
(tag common-lisp:t)
((eql :oid) odb)
(reference common-lisp:t)

Iterating

function (revision-walk commits &key (ordering :time))

Create a revision walker starts iteration from the COMMITS listed.

The ordering can be adjusted to :NONE :TOPOLOGICAL :REVERSE or :TIME, which is the default.

Once created iteration over commits can be done with the method NEXT-REVISION method.

generic (next-revision walker)

Returns the next object for the walker. If no objects are available anymore return nil.

Specializers:
(revision-walker)

To walk commits, REVISION-WALK and NEXT-REVISION are provided.

GIT> (let ((repository (open-repository (merge-pathnames #p"projects/ecl"
                                           (user-homedir-pathname)))))
       (loop
         :with walker = (revision-walk
                         (get-object 'commit "ea010dee347e50666331b77edcf0588735c3205a"
                                     repository))
         :for revision = (next-revision walker)
         :until (null revision)
         :collect revision))

(#<COMMIT EA010DEE347E50666331B77EDCF0588735C3205A {1007BA1003}>
 #<COMMIT F2DA18A5913EEA2D3F8BBD336F08AB48D9D3ECCE {1007BA1253}>
 #<COMMIT DC4DF60020DF2BFF026B26E6227127F6A3CC9FC {1007BA14A3}>
 #<COMMIT FE8BCD1B8BD27891F260892CC16BBA4A93999D89 {1007BA16F3}>
 #<COMMIT 2D8D0CD44B87C724ACBCA9F835C2142778007DA9 {1007BA1943}>)

Inspecting

generic (message object)

Return the message associated with OBJECT.

For example for commits this will return the commit message and for tags the message associated with the tag.

GIT> (message
      (get-object 'commit "ea010dee347e50666331b77edcf0588735c3205a"
                  (open-repository #p"/home/russell/projects/ecl/")))
"Add new declaration, si::c-export-fname, which produces lisp compiled files with
meaningful names for the exported functions. For instance,
    (proclaim '(si::c-export-fname union))
is used to produce a C function with name clLunion, which can be directly used
in other compiled files. This feature has been applied to almost all functions
in the Lisp runtime.
"
Specializers:
(reflog-entry)
(commit)
(tag)

generic (author object)

Returns the author's signature of OBJECT.

A signature is a list with the keys :NAME :EMAIL and :TIME. The :NAME and :EMAIL values are strings, and the :TIME value is LOCAL-TIME timestamp.

GIT> (author
      (get-object 'commit "ea010dee347e50666331b77edcf0588735c3205a"
                  (open-repository #p"/home/russell/projects/ecl/")))
(:NAME "jjgarcia"
 :EMAIL "jjgarcia"
 :TIME @2001-07-13T02:32:15.000000+10:00
 :TIMEZONE #<LOCAL-TIME::TIMEZONE +0000>)
Specializers:
(commit)

generic (committer object)

Returns the committer's signature of OBJECT.

A signature is a list with the keys :NAME :EMAIL and :TIME. The :NAME and :EMAIL values are strings, and the :TIME value is LOCAL-TIME timestamp.

GIT> (committer
      (get-object 'commit "ea010dee347e50666331b77edcf0588735c3205a"
                  (open-repository #p"/home/russell/projects/ecl/")))
(:NAME "jjgarcia"
 :EMAIL "jjgarcia"
 :TIME @2001-07-13T02:32:15.000000+10:00
 :TIMEZONE #<LOCAL-TIME::TIMEZONE +0000>)
Specializers:
(reflog-entry)
(commit)

generic (parents commit)

GIT> (parents
      (get-object 'commit "ea010dee347e50666331b77edcf0588735c3205a"
                  (open-repository #p"/home/russell/projects/ecl/")))
(#<COMMIT F2DA18A5913EEA2D3F8BBD336F08AB48D9D3ECCE (weak) {100559E5A3}>)
Specializers:
(commit)

generic (commit-tree commit)

To see the state of the repository when this commit was made, use the COMMIT-TREE.

GIT> (commit-tree
      (target
       (repository-head
        (open-repository (merge-pathnames #p"projects/ecl"
                                          (user-homedir-pathname))))))
#<TREE 96F8A446E020204589710FE1BF0CE1DD5B5B5AD0 {10079C9C03}>
Specializers:
(commit)