Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

git

github

grit

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?

like image 784
Jonathan C. Avatar asked Jul 27 '11 14:07

Jonathan C.


People also ask

How do I add files to a GitHub repository?

On GitHub.com, navigate to the main page of the repository. Above the list of files, using the Add file drop-down, click Upload files. Drag and drop the file or folder you'd like to upload to your repository onto the file tree.

How do I add changes to a Git repository?

Enter git add --all at the command line prompt in your local project directory to add the files or changes to the repository. Enter git status to see the changes to be committed. Enter git commit -m '<commit_message>' at the command line to commit new files/changes to the local repository.


1 Answers

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:

  • git hash-object
  • git cat-file
  • git ls-tree
  • git mk-tree
like image 81
Colin Hebert Avatar answered Oct 17 '22 17:10

Colin Hebert