12

Some Context

what this fits into

A collaboration focused web application that offers git hosting (as bare repos)

what we want to do

Allow users to add a set of files directly to their existing repositories.

My Question

Is there a tool or method to manually create a commit that only involves adding new files to a git repo?

We're able to do this now using temporary server-side sparse checkouts but we would like to optimize this process.

6
  • What do you mean "create a commit that only involves adding new files"? How is that any different than a normal commit? Commented Mar 12, 2012 at 15:53
  • It sounds like you want to have a web application where people can upload files, and those files, on the backend, get committed to a git repo? What language is the web site in? You would likely need to find a library to interact with git for whatever language you are using. Commented Mar 12, 2012 at 16:07
  • @rally25rs We are using a python wsgi app but we're not as concerned with what language or packages we need to use to do this. Any method can be triggered from the site as a subprocess.
    – rennat
    Commented Mar 12, 2012 at 18:37
  • I'm also interested in this topic; I need it for phorkie, my git based pastebin tool.
    – cweiske
    Commented Apr 4, 2012 at 9:52
  • This issue has been on my back burner while working out other parts of the platform but I will need to readdress it soon. If no module or library can be found I would like to start one as a lightweight open source project. For our platform making this a Python module makes sense but it would be beneficial to do it in a common format with multiple language bindings. If anyone is interested in contributing or leading this small project please let me know.
    – rennat
    Commented Apr 4, 2012 at 17:46

3 Answers 3

12

The plumbing and porcelain page sort of have an example of this, but I'll try to simplify it.

It seems bare repos still have an index, which can be manipulated and made into a commit. It's probably also possible to create tree object from scratch, but I'm not aware of exactly how.

You probably have to lock the repository if there's a risk someone else might access it at the same time. I'll simply use lockfile from the procmail package here.

#!/bin/bash
cd myrepo.git

MY_BRANCH=master
MY_FILE_CONTENTS=$'Hello, world!\n'

# Note this is just a lock for this script. It's not honored by other tools.
lockfile -1 -r 10 lock || exit 1

PARENT_COMMIT="$(git show-ref -s "$MY_BRANCH")"

# Empty the index, not sure if this step is necessary
git read-tree --empty

# Load the current tree. A commit ref is fine, it'll figure it out.
git read-tree "${PARENT_COMMIT}"

# Create a blob object. Some systems have "shasum" instead of "sha1sum"
# Might want to check if it already exists. Left as an excercise. :)
BLOB_ID=$(printf "blob %d\0%s" $(echo -n "$MY_FILE_CONTENTS" | wc -c) "$MY_FILE_CONTENTS" | sha1sum | cut -d ' ' -f 1)
mkdir -p "objects/${BLOB_ID:0:2}"
printf "blob %d\0%s" $(echo -n "$MY_FILE_CONTENTS" | wc -c) "$MY_FILE_CONTENTS" | perl -MCompress::Zlib -e 'undef $/; print compress(<>)' > "objects/${BLOB_ID:0:2}/${BLOB_ID:2}"

# Now add it to the index.
git update-index --add --cacheinfo 100644 "$BLOB_ID" "myfile.txt"

# Create a tree from your new index
TREE_ID=$(git write-tree)

# Commit it.
NEW_COMMIT=$(echo "My commit message" | git commit-tree "$TREE_ID" -p "$PARENT_COMMIT")

# Update the branch
git update-ref "refs/heads/$MY_BRANCH" "$NEW_COMMIT" "$PARENT_COMMIT"

# Done
rm -f lock

It'd be nice if there were git commands to create blobs, but I didn't find one. The perl command was taken from another question.

1
  • As for how to create a tree/blob object from scratch, there seems to be a command called git hash-object that can do that for you, and it also adds it to the object store when passing it the -w flag. git-scm.com/docs/git-hash-object
    – Qqwy
    Commented Oct 24, 2015 at 22:25
3

The "Plumbing and Porcelain" chapter of Pro Git provides some insight into the internals of Git, which you could leverage into a way to create commits while bypassing some of the normal Git process.

1
  • 1
    Never fully resolved this but congrats on having the best answer!
    – rennat
    Commented Jun 27, 2012 at 16:37
2

I created the sample for git add/rm files into bare repo using JGit. Check out https://github.com/junoyoon/git-online-commit-sample. In the test code you can know how to use JGit APIs for bare repo manipulation.

Not the answer you're looking for? Browse other questions tagged or ask your own question.