SkillAgentSearch skills...

Cppgit2

Git for Modern C++ (A libgit2 Wrapper Library)

Install / Use

/learn @p-ranav/Cppgit2

README

<p align="center"> <img height="100" src="img/logo.png"/> </p> <p align="center"> <a href="https://en.wikipedia.org/wiki/C%2B%2B11"> <img src="https://img.shields.io/badge/C%2B%2B-11-blue.svg" alt="standard"/> </a> <a href="https://github.com/p-ranav/tabulate/blob/master/LICENSE"> <img src="https://img.shields.io/badge/License-MIT-yellow.svg" alt="license"/> </a> <img src="https://img.shields.io/badge/version-0.1.0-blue.svg?cacheSeconds=2592000" alt="version"/> </p>

cppgit2 is a libgit2 wrapper library for use in modern C++ ( >= C++11). See the Build and Integration section for details on how to build and integrate cppgit2 in your projects.

// Create new repo
std::string repo_name = "my_project";
auto repo = repository::init(repo_name, false);

// Write README file
std::string file_name = "README.md";
auto readme = std::ofstream(repo_name + "/" + file_name);
readme << "Hello, World!\n";
readme.close();

// Stage README.md
auto index = repo.index();
index.add_entry_by_path(file_name);
index.write();

// Prepare signatures
auto author = signature("foobar", "foo.bar@baz.com");
auto committer = author;

// Create commit
auto tree_oid = index.write_tree();
repo.create_commit("HEAD", author, committer, "utf-8", "Update README",
    repo.lookup_tree(tree_oid), {});

Table of Contents

Build and Integration

Run the following commands to build cppgit2.

NOTE: This also builds libgit2 from source. libgit2 is a submodule in the ext/ directory that points to a stable release commit, e.g., v1.0.0.

git clone --recurse-submodules -j8 https://github.com/p-ranav/cppgit2
cd cppgit2
mkdir build && cd build
cmake .. && make

The build output is in four directories: include, lib, samples and test:

include/
├── cppgit2/
├── git2/
└── git2.h
lib/
├── libcppgit2.so -> libcppgit2.so.1
├── libcppgit2.so.0.1.0
├── libcppgit2.so.1 -> libcppgit2.so.0.1.0
├── libcppgit2.static.a
├── libgit2_clar
├── libgit2.pc
├── libgit2.so -> libgit2.so.0
├── libgit2.so.1.0.0
├── libgit2.so.0 -> libgit2.so.1.0.0
└── ...
samples/
test/

For integration in your projects,

  • Add build/include to your include_directories
  • Add build/lib to your link_directories
  • Build your application, linking with cppgit2
  • Add build/lib to your LD_LIBRARY_PATH to load the shared libraries at runtime.

Here's an example using g++:

g++ -std=c++11 -Ibuild/include -Lbuild/lib -o my_sample my_sample.cpp -lcppgit2
export LD_LIBRARY_PATH=build/lib:$LD_LIBRARY_PATH
./my_sample

and the same example with CMake:

PROJECT(my_sample)
CMAKE_MINIMUM_REQUIRED(VERSION 3.8)

INCLUDE_DIRECTORIES("build/include")
ADD_EXECUTABLE(my_sample my_sample.cpp)
find_library(CPPGIT2_LIBRARY cppgit2 HINTS ./build/lib)
TARGET_LINK_LIBRARIES(my_sample ${CPPGIT2_LIBRARY})
SET_PROPERTY(TARGET my_sample PROPERTY CXX_STANDARD 11)

Sample Programs

This section presents some simple examples illustrating various cppgit2 features. You can find the full set of available examples in the /samples directory. Samples are still a work-in-progress. Pull requests are welcome here.

Initialize a new repository (git init)

To initialize a new repository, simply call repository::init.

#include <cppgit2/repository.hpp>
using namespace cppgit2;

int main() {
  auto repo = repository::init("hello_world", false);
}

If you want to create a bare repository, set the second argument to true.

Clone a repository and checkout specific branch (git clone --branch)

Let's say you want to clone a repository and checkout a specific branch. Construct an options object using clone::options, set the checkout branch name, and then use repository::clone to clone the repository.

#include <cppgit2/repository.hpp>
using namespace cppgit2;

int main() {
  auto url = "https://github.com/fffaraz/awesome-cpp";
  auto branch_name = "gh-pages";
  auto path = "awesome_cpp";

  // Prepare clone options
  clone::options options;
  options.set_checkout_branch_name(branch_name);

  // Clone repository
  auto repo = repository::clone(url, path, options);
}

Open an existing repository

You can open an existing repository with repository::open.

#include <cppgit2/repository.hpp>
using namespace cppgit2;

int main() {
  auto path = "~/dev/foo/bar";          // bar must contain a .git directory
  auto repo = repository::open(path);
}

Use repository::open_bare to open a bare repository.

Create Remote (git remote)

#include <cppgit2/repository.hpp>
#include <iostream>
using namespace cppgit2;

int main(int argc, char **argv) {
  if (argc == 2) {

    // Create new repo
    auto repo = repository::init(argv[1], false);

    // Create remote
    auto remote = repo.create_remote("origin", "https://github.com/p-ranav/test");

  } else {
    std::cout << "Usage: ./executable <new_repo_path>\n";
  }
}
$ ./create_remote foo

$ cd foo

$ git remote -v
origin	https://github.com/p-ranav/test (fetch)
origin	https://github.com/p-ranav/test (push)

Add and Commit a File (git add, git commit)

#include <cppgit2/repository.hpp>
#include <fstream>
#include <iostream>
using namespace cppgit2;

int main(int argc, char **argv) {
  if (argc == 2) {
    // Create new repo
    auto repo = repository::init(argv[1], false);

    // Write README file
    std::ofstream readme;
    readme.open(std::string{argv[1]} + "/README.md");
    readme << "Hello, World!";
    readme.close();

    // Stage README.md
    auto index = repo.index();
    index.add_entry_by_path("README.md");
    index.write();
    auto tree_oid = index.write_tree();

    // Prepare signatures
    auto author = signature("foobar", "foo.bar@baz.com");
    auto committer = signature("foobar", "foo.bar@baz.com");

    // Create commit
    auto commit_oid =
        repo.create_commit("HEAD", author, committer, "utf-8", "Update README",
                           repo.lookup_tree(tree_oid), {});

    std::cout << "Created commit with ID: " << commit_oid.to_hex_string()
              << std::endl;

  } else {
    std::cout << "Usage: ./executable <new_repo_path>\n";
  }
}
$ ./commit_file foo
Created commit with ID: 34614c460ee9dd6a6e56c1a90c5533b7e284b197

$ cd foo

$ cat README.md
Hello, World!

$ git log --stat
commit 34614c460ee9dd6a6e56c1a90c5533b7e284b197 (HEAD -> master)
Author: foobar <foo.bar@baz.com>
Date:   Thu Mar 19 20:48:07 2020 -0500

    Update README

 README.md | 1 +
 1 file changed, 1 insertion(+)


Walk Repository Tree (git ls-tree)

#include <cppgit2/repository.hpp>
#include <iostream>
using namespace cppgit2;

int main(int argc, char **argv) {
  if (argc == 2) {
    auto repo = repository::open(argv[1]);

    auto head = repo.head();
    auto head_commit = repo.lookup_commit(head.target());
    auto tree = head_commit.tree();

    tree.walk(tree::traversal_mode::preorder,
              [](const std::string &root, const tree::entry &entry) {
                  auto type = entry.type();
                  std::string type_string{""};
                  switch (type) {
                  case object::object_type::blob:
                    type_string = " - blob";
                    break;
                  case object::object_type::tree:
                    type_string = "tree";
                    break;
                  case object::object_type::commit:
                    type_string = " - commit";
                    break;
                  default:
                    type_string = "other";
                    break;
                  }
                  std::cout << type_string << " [" << entry.id().to_hex_string(8)
                            << "] " << entry.filename() << std::endl;
              });

  } else {
    std::cout << "Usage: ./executable <repo_path>\n";
  }
}

Running this program on the cppgit2 repository yields the following:

$ cd cppgit2

$ ./build/samples/walk_tree .
 - blob [ae28a6af] .clang-format
 - blob [e4bbfcd3] .gitignore
 - blob [7f2703f2] .gitmodules
 - blob [3ed1714f] CMakeLists.txt
 - blob [f6857659] README.md
 - blob [9f435d50] clang-format.bash
tree [4352ee62] ext
 - commit [17223902] libgit2
tree [7eed768f] img
 - blob [d0fa9dbe] init_add_commit.png
 - blob [dc19ed13] logo.png
tree [4d47c532] include
tree [c9adc194] cppgit2
 - blob [ca1b6723] annotated_commit.hpp
 - blob [4f168526] apply.hpp
 - blob [79ac5ed9] attribute.hpp
 - blob [5bf06b5a] bitmask_operators.hpp
 - blob [10546242] blame.hpp
 - blob [1a9107ab] blob.hpp
 - blob [2bce809e] branch.hpp
 - blob [a56ff9
View on GitHub
GitHub Stars120
CategoryDevelopment
Updated16d ago
Forks25

Languages

C++

Security Score

100/100

Audited on Mar 15, 2026

No findings