Rust has a crate git2, which is a wrapper over libgit2 to work with git repositories.
Primary data structure to work with git repositories is
git2::Repository. Everything is tied to repository, all objects, eg Commit, Branch etc have a lifetime linked to repository, so this is going to be starting point for everything.
git2::Repository object can be created by referring to an existing git repository on filesystem using:
let repo = git2::Repository::open("/path/to/a/repo")?;
Or we can create a new git repository (equivalent of
let repo = git2::Repository::init("/path/to/a/repo")?;
Or we can clone repository using a git url:
let repo = match Repository::clone(url, "/path/to/a/repo")?;
_bare() versions too, if you are working with bare git repositories.
::open() can be used with either bare or normal git repository.
git2::Repository may have a “workdir” if it is a “normal” repository, or not, if it is a “bare” repository.
We can get the workdir for a repository using
git2::Repository.workdir() -> Option<&Path>. Similarly, there is
When setting a workdir to a repository, we can pass a flag update_gitlink, which will set
core.worktree to the workdir passed in the bare repository (else the information will only be kept in the in-memory version of
A git repository can be thought of as a collection of objects (
git2::Object), where objects usually represent a file (blob), a tree (collection of files in any folder, non recursive, tree is composed of blobs and trees), commits and tags (these types are represented using git2::ObjectType enum.)
Each of above objects are stored with an id which is hash of content (and header, where header represents type of object and size of content). These ids are called
References on the other hand are like aliases to these object ids. Common references are branches. And a reference for HEAD which represents the commit associated with the workdir.
A simplified story: a repository is collection of branches, which are references. A branch is a reference to the latest commit. Each commit stores zero, one or two to parent commit object ids, a tree object id representing content of repository at that commit, commit message, author info, and date time of commit.
Branches are represented by
git2::Branch struct. To find branches of a repository there is a
.branches() method. Then there is a
.find_branch() method to find a branch by name.
git2::Branch you can find
.into_reference()), and from Reference you can get the Oid using
.target(), or straight to Commit (
.peel_to_commit()) or Tree (
.peel_to_tree()) for the the reference.
To checkout the content of a Tree (that say you found via
Branch -> Reference -> peel_to_tree()), you can do:
Repository.checkout_tree(), which will update the working directory and the repositories index.
You can also checkout write the content of Index to working directory using
Repository.checkout_index(), or you can checkout HEAD using
Repository.checkout_head(), which will reset both index and working directory to the commit pointed to by
When using command git command line, there is a “index”, which is stored in
git add updates index, and
git commit created a commit out of index.
git2, index can either represent the index on disc, or in memory version.
To get the reference to
git2::Index stored in a Repository, use
Repository.index() method, which will read the
.git/index file and use the same index used by
git command line tool. Or to create new in-memory index,