How does Github allow for inline file editing? (Or how to add or edit files in a bare git repository)
Asked Answered
C

1

7

I have a small application that manages several git repositories similar to Github/Gitorious. Github allows for inline file editing, and I'd like to know if anyone has any idea on how they manage this.

My initial thought was that it would do a complete clone of the repository, use your submission to replace the file, commit, and push, but this seems like an very expensive operation with large repositories like the linux kernel.

Any ideas on a more efficient way to add and edit files to a bare repository?

Cohn answered 27/7, 2011 at 14:26 Comment(0)
U
8

You can use plumbing commands.

Get your current HEAD, get the tree from there then your blobs.

Once you have the blob you can put the content in a textbox. When it's finished you just have to hash the new blob, create the new tree, the new commit and tadaam. It's "pushed".

PS: Remember you're in a bare repository, so check that every command you use don't need the index nor the working directory.


As it has been asked here is a step by step example.

First we get the current file content:

> git cat-file -p HEAD:var/test/text.txt
test

We do our little modification on that content and now have a new content ready to be pushed. To save that content we're going to hash it:

> git hash-object -t blob -w var/test/text.txt
9764d221e6b50063b83c0268544c5d5b745ec9c5

This will save it, and return a sha-1 of that object (blob), the very next step consist in creating a new folder test which will contain our text.txt file. But first let's look at what does the current test folder look like:

> git ls-tree HEAD:var/test
100644 blob 9daeafb9864cf43055ae93beb0afd6c7d144bfa4    text.txt

So what we want to do here, is replace the previous SHA-1 (9daeafb...) with the new one (9764d22...) and generate a new tree based on that (pay attention to the \t).

> echo -e "100644 blob 9764d221e6b50063b83c0268544c5d5b745ec9c5\ttext.txt" | git mktree
b7788f9e8e9a24be31188167a6a0bc1de9e41d24

Great, so now we have the new file text.txt and the parent folder test, we now need var.

> git ls-tree HEAD:var
040000 tree 9bfb857f532d280ecd7704beb40a2ea4ba332f5a    test

> echo -e "040000 tree b7788f9e8e9a24be31188167a6a0bc1de9e41d24\ttest" | git mktree
536f33626a47138499fade7df6d02327f75d80be

and now we need the parent of var (which is the root of our repository):

> git ls-tree HEAD
040000 tree 31a6ee5e7d14a0569721632a05234185a109d6bd    var

> echo -e "040000 tree 536f33626a47138499fade7df6d02327f75d80be\tvar" | git mktree
7db3d6bc14cce98ff89ccc285b9d17965f5ca92b

And it's done, our tree is ready. The only thing missing is the actual commit:

> git commit-tree -p HEAD -m "commit message" 7db3d6bc14cce98ff89ccc285b9d17965f5ca92b
4aa2de2cf9e3e4f5470bcd1ee1e83ef6e4025eaf

But it isn't ready yet, now we want the commit to be the HEAD, so the very last step is:

> git update-ref HEAD 4aa2de2cf9e3e4f5470bcd1ee1e83ef6e4025eaf

And now we're done.


Resources:

Ustkamenogorsk answered 27/7, 2011 at 14:42 Comment(2)
Thanks a lot! The keyword that helped was git 'plumbing'.Cohn
could you make a small example how to add some file (like /var/test/text.txt) ? or overwrite the same one?Pawsner

© 2022 - 2024 — McMap. All rights reserved.