Commits

CLOS class commit
Superclass:

[‘T’]

Metaclass:

standard-class

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 update 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 (eq COMMIT)) (id/name T) (repository T))

Return an object of type CLASS from the object database. The lookup will use either an oid or a name to find the object.

See also: get-object

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.

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)
(next-revision (walker CL-GIT::REVISION-WALKER))

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

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)
(message (commit COMMIT))
(message (reflog-entry REFLOG-ENTRY))
(message (tag TAG))

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.
"
Generic (message-trailers message)
(message-trailers (message STRING))
(message-trailers (message COMMIT))

Read the message trailers and return a list of them.

GIT> (message-trailers
      (get-object 'commit "ea010dee347e50666331b77edcf0588735c3205a"
                  (open-repository #p"/home/russell/projects/ecl/")))
'((:key "Fixes" :value "https://example.com/foobar")
  (:key "Signed-off-by" :value "John Doe <john@doe.example.com>"))
Generic (author object)
(author (commit COMMIT))

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>)
Generic (committer object)
(committer (commit COMMIT))
(committer (reflog-entry REFLOG-ENTRY))

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>)
Generic (parents commit)
(parents (commit COMMIT))

Returns a list of oids identifying the parents of OBJECT.

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

Returns the TREE object of the 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}>

Graph Traversal

Generic (reachable-from repository commit commits)
(reachable-from (repository REPOSITORY) (commit COMMIT) (commits T))

Return T if given commit is an ancestor of any of the given potential descendant commits.

GIT> (with-repository (repository (merge-pathnames
                                   #p"projects/cl-git"
                                   (user-homedir-pathname)))
      (reachable-from
       repository
       (resolve (car (list-objects 'tag repository)) '(commit))
       (list (get-object 'reference "refs/heads/master" repository))))
T