Question

I want to use Git as a storage backend for a bunch of textfiles (a wiki). It looks like libgit2 is the tool for the job. I think it lets me skip the step of having working copies of the files (in the file system) and thus enabling several concurrent edits. But I'm not clear on the details. I want it to work like this: Get the current content of a file along with the ID of the last commit. (I've got this part working.) Let the user make changes to the content. Then write the content back:

  1. Check if the content of the file differs from the last commit. If not, do nothing further.

  2. Check if any new commits have been made (based on the same parent commit) and try to merge with them. But a conflicting branch is also acceptable.

  3. Create a new commit with only the new content of this file.

I'm not even sure how much of this is needed to be done manually and what is automated by libgit2. For example I could retrieve the file content from the last commit and check for changes myself, but I suspect there is an easier way. Which are the relevant functions I need to call in order to achieve this?

Was it helpful?

Solution

A lot of this depends on what your application does. How to deal with concurrent edits isn't something Git handles. It lives a layer above. In the typical case in the user's merge tool, here you'll either have to push the work to the user or figure out a way inside your application to deal with conflicts.

Check if the content of the file differs from the last commit. If not, do nothing further.

You can run diff between an arbitrary buffer and an object. See git_diff_blob_to_buffer().

Check if any new commits have been made (based on the same parent commit) and try to merge with them. But a conflicting branch is also acceptable.

There's the merge API to perform the merge and detect the merge base (which you can use to tell if there has been any divergence). If the merge doesn't succeed, it's up to you what to do. These require human intervention (or use of a different merge algorithm that knows about the semantics of the contens).

Create a new commit with only the new content of this file.

This is most likely not what you want. A commit in Git is a snapshot, so with this, you'd be deleting every other file. Assuming that what you want is a new commit with a particular file updated, create an empty index and fill it with the base commit's tree, update the entry and write out the index as a tree, which you can use for the new commit. All of this in available in the index API.

There are a few program that deal with different aspects of this, such as Gollum which is a git-backed wiki, SparkleShare which is a git-backed file synchronisation tool and Docurium which writes out documentation directly into a new commit in a branch.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top