Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Git create remote repository on push

I have been trying to figure this one out but I am having a hard time doing so. I am currently working on an open source project that requires me to allow a user to push to remote repository without it already existing there. I want to avoid manually logging in to a server and running git init or git init --bare.

For obvious reasons, I get the following error when trying to push my local repository to a path that doesn't point to an existing repository on the remote server:

fatal: '/var/repositories/myrepo' does not appear to be a git repository fatal: The remote end hung up unexpectedly 

But I would like to be able to run for example the following command:

git push origin master 

And have that create /myrepo in /var/repositories if it does not yet exist. How would I be able to accomplish this? I would assume it is some kind of (global) git config setting you would probably set on the remote server, or otherwise a (repository specific) git config locally, but I couldn't figure it out.

Any help would be much appreciated!

Thanks!

like image 838
Michael van Rooijen Avatar asked Nov 05 '10 15:11

Michael van Rooijen


People also ask

How do I create a repository to push on GitHub?

In the command line, navigate to the root directory of your project. Initialize the local directory as a Git repository. To create a repository for your project on GitHub, use the gh repo create subcommand. When prompted, select Push an existing local repository to GitHub and enter the desired name for your repository.

How do I push a new remote repository?

To push the commit from the local repo to your remote repositories, run git push -u remote-name branch-name where remote-name is the nickname the local repo uses for the remote repositories and branch-name is the name of the branch to push to the repository. You only have to use the -u option the first time you push.

How do I create a push and branch to remote repository?

Push a new Git branch to a remote repoClone the remote Git repo locally. Create a new branch with the branch, switch or checkout commands. Perform a git push with the –set-upstream option to set the remote repo for the new branch. Continue to perform Git commits locally on the new branch.


2 Answers

There is currently no way to use git push to create a repository on the remote. The best you can do is write a one-liner script something like this:

#!/bin/bash ssh $1 "git init --bare $2" && git push ssh://$1/$2 

Hopefully you can ssh in; if you can't, you could use some kind of filesystem access to just manually create the repo by dumping in the appropriate file/directory structure (maybe create it locally and copy). You might also create a named remote along the way.

This was actually one of the most requested features on the 2010 Git Survey - so maybe you'll get your wish sometime in the next year!

like image 154
Cascabel Avatar answered Sep 25 '22 10:09

Cascabel


You can write a wrapper script on the remote, and prepend command="/path/to/wrapper" to the authorized_keys' lines.

command="/usr/local/bin/gitaccess" ssh-rsa ... 

In this wrapper you would check SSH_ORIGINAL_COMMAND. Git issues these commands:

git receive-pack '/path/provided' # when pushing git upload-pack '/path/provided' # when pulling 

If SSH_ORIGINAL_COMMAND is not empty and starts with one of these, you check the path, create the repository if necessary, install any configuration you need in it, and execute the command.

If SSH_ORIGINAL_COMMAND is empty and you want to provide users with shell access, you invoke a shell.

If SSH_ORIGINAL_COMMAND is not empty but doesn't start with a git command, if you want to allow users to have shell access, you just execute the command provided.

Here's a bit of Ruby code to demonstrate. Note that I didn't test it and there's room for improvement (for example we should not hardcode /bin/bash).

#!/usr/bin/env ruby orig_command = ENV['SSH_ORIGINAL_COMMAND'] if orig_command.nil?     # If you want to preserve shell access     exec '/bin/bash' # not tested, I hope it's interactive if executed this way end  cmd_parts = orig_command.match /([a-z-]+) '([a-z0-9.\/]+)'/ if cmd_parts.nil?     # If you want to preserve shell access     exec '/bin/bash', '-c', orig_command end  command = cmd_parts[1] path = '/var/repositories/'+cmd_parts[2] # not secured (could contain '..')  if command == 'git-receive-pack' || command == 'git-upload-pack'     if not File.directory?(path)         `git init --bare #{path}` # not secured, I didn't escape path         # Do any configuration here     end     exec 'git-shell', '-c', "#{command} '#{path}'" end  # If you want to preserve shell access exec '/bin/bash', '-c', orig_command 

You can also pass an argument to this script in the authorized_keys to identify users and choose whether they should have shell access. I also do this to control access on a per-repository basis. If you want to carry this argument to the git hooks, just create an environment variable.

like image 44
Pikrass Avatar answered Sep 24 '22 10:09

Pikrass