Search code examples
c++clibgit2

How to commit to a git repository using libgit2?


Since there is no copy-paste example for creating a commit without using files on disk with libgit2 as far as I can tell I thought I should add one.

Don't forget that libgit2 is in full development at this time (March 2013) so have a look at official documentation and source code, as new features are added daily:


Solution

  • bool addGitCommit ( 
      git_repository * repo, git_signature * sign, 
      const char * content, int content_sz,
      const char * message )
    {
      int rc;              /* return code for git_ functions */
      git_oid oid_blob;    /* the SHA1 for our blob in the tree */
      git_oid oid_tree;    /* the SHA1 for our tree in the commit */
      git_oid oid_commit;  /* the SHA1 for our initial commit */
      git_blob * blob;     /* our blob in the tree */
      git_tree * tree_cmt; /* our tree in the commit */
      git_treebuilder * tree_bld;  /* tree builder */
      bool b = false;
    
      /* create a blob from our buffer */
      rc = git_blob_create_frombuffer( 
            &oid_blob,
            repo, 
            content, 
            content_sz );
      if ( rc == 0 ) { /* blob created */
        rc = git_blob_lookup( &blob, repo, &oid_blob );
        if ( rc == 0 ) { /* blob created and found */
          rc = git_treebuilder_create( &tree_bld, NULL );
          if ( rc == 0 ) { /* a new tree builder created */
            rc = git_treebuilder_insert( 
                  NULL, 
                  tree_bld, 
                  "name-of-the-file.txt", 
                  &oid_blob, 
                  GIT_FILEMODE_BLOB );
            if ( rc == 0 ) { /* blob inserted in tree */
              rc = git_treebuilder_write( 
                    &oid_tree, 
                    repo, 
                    tree_bld );
              if ( rc == 0 ) { /* the tree was written to the database */
                rc = git_tree_lookup(
                      &tree_cmt, repo, &oid_tree );
                if ( rc == 0 ) { /*we've got the tree pointer */  
                  rc = git_commit_create(
                        &oid_commit, repo, "HEAD",
                        sign, sign, /* same author and commiter */
                        NULL, /* default UTF-8 encoding */
                        message,
                        tree_cmt, 0, NULL );
                  if ( rc == 0 ) {
                    b = true;
                  }
                  git_tree_free( tree_cmt );
                }
              }
            }
            git_treebuilder_free( tree_bld );
          }
          git_blob_free( blob );
        }
      }
      return b;
    }
    

    The repository comes from git_repository_init() or git_repository_open(). The signature comes from git_signature_now() or git_signature_new().

    The function updates the HEAD for current branch.

    If you do a git status after the function executes you will notice that the file name-of-the-file.txt appears as being deleted. That is because the function does not create an actual file, only an entry in the git database.

    Also, note the last arguments of git_commit_create(). 0 and NULL means that this is the first (root) commit. For all other there should be at least a parent commit specified, maybe obtained using git_commit_lookup().


    I'm just learning these things. Please improve this answer if you know better.