I want to use version control but, due to security reasons, the server I'm working on has no internet access: I can only move files on a USB flash drive. Can I still use Git with this setup? Can I create small patches that I can apply on a Git repository?
5 Answers
Sure, there's nothing about Git that requires a particular protocol. Just out of the box the standard client supports HTTP(S), SSH, the custom Git protocol and, importantly, the local protocol. That just takes a path to a local .git
directory, which can be within working directory (/path/to/project/.git
) or just a bare directory (/path/to/project.git
), though the naming is just a convention.
This means you can, of course, add a flash drive as a remote:
git remote add origin /mnt/flashdrive/foo.git
or, on Windows:
git remote add origin F:\foo.git
Or even add it as an additional remote with a different name (if you prefer origin
to point towards an Internet server somewhere):
git remote add flashdrive /mnt/flashdrive/foo.git
Then you can just push/pull to/from this remote just like any other.
If you read the documentation, you'll notice there's also a file://
protocol that behaves slightly differently. It is recommended to use a local path as that will make use of some additional optimisations - if you use the file://
protocol then git will use some standard network components (to talk to the local disk), which is slower.
-
50To add to this exceptional answer - It may also be worthwhile to investigate using a 'bare' respository on the flash drive. 'bare' repositories don't have a working tree, and so cut out a category of potential issues when used as a shared 'point of authority', which sounds like the OP's use-case. Oct 17, 2018 at 15:36
-
5The
file://
is also a bit more flexible. It allows you to use some features (like shallow clones) that you can't with a local path. Oct 17, 2018 at 15:53 -
1@IronGremlin Could you expand on this "shared point of authority" notion? I'm not a Git expert and I'm curious what you mean by it. Oct 18, 2018 at 17:39
-
2@LightnessRacesinOrbit - This is a pretty dense topic, but, basically, git is distributed, so everyone gets their own history. A can ask B for their version of history, but C doesn't know about it unless someone tells them. Having a single repository to store the 'authoritative' history means D acts as a clearing house for histories. So, A tells D about changes, and B and C know to talk to D to stay up to date, rather than doing side-channel stuff amongst themselves. Case in point, if OP's server is C, and the flash drive is D, it makes sure the server doesn't get left out of A/B interactions. Oct 18, 2018 at 17:58
-
6@LightnessRacesinOrbit Important to note here that bare doesn't have to mean authoritative, it's just useful in that context. For example, it's also useful because, lacking a working tree, it's a smaller diskspace (or bandwidth) footprint. This used to be a hell of a lot more important than it is now, but still comes up. Oct 18, 2018 at 18:12
On a single computer, nothing special is needed. Run git init
in your desired directory and work with Git as you normally would.
For synchronizing a repository across multiple computers, there are several methods.
Method 1a (no network at all): You can create a 'bare repository' on the USB stick, then push to it and pull from it as you would with any other remote repository. In other words, repository operations via local paths aren't any different from operations via SSH or HTTPS URLs.
Create a 'remote' repository:
$ git init --bare /mnt/Stick/Repositories/Large_Project.git
In computer 1, push everything to it:
$ cd ~/Large_Project $ git remote add usb /mnt/Stick/Repositories/Large_Project.git $ git push usb master
In computer 2, well, same as always.
$ git remote add usb /mnt/Stick/Repositories/Large_Project.git $ git pull usb
(You can push/fetch/pull from a URL or path directly, too.)
Method 1b (internal network): If you have an internal server with SSH available, and if it has Git installed, you can do the same as above, just specify an SSH address using the [user@]host:path
or ssh://[user@]host/path
syntax.
Create a 'remote' repository by running
git init --bare <somepath.git>
on the designated server (via SSH).In computer 1, the same way as demonstrated earlier.
$ git remote add origin myserver.example.com:Gits/Large_Project.git
Or if you prefer:
$ git remote add origin ssh://myserver.example.com/~/Gits/Large_Project.git
In computer 2, again the same as method 1a.
Method 2: You can create 'transfer bundles' which archive a given list of commits into a single file.
Unfortunately the bundle commands don't automatically remember what was already bundled the last time, so manual tagging or note-keeping is needed. I'll just take the examples from the git-bundle manual.
In computer 1, create a bundle of the entire branch:
$ cd ~/Large_Project $ git bundle create /mnt/Stick/Project.bundle master $ git tag -f last-bundled master
In computer 2, pull from the bundle as if it were a repository:
$ cd ~/Large_Project $ git pull /mnt/Stick/Project.bundle
Subsequent bundles don't need to pack the whole master
– they can pack just the newly added commits from last-bundled..master
instead.
In computer 1, create a bundle of the newly added commits:
$ cd ~/Large_Project $ git bundle create /mnt/Stick/Project.bundle last-bundled..master $ git tag -f last-bundled master
Same as above.
-
actually it would not be bad for my purposes, also in git nothing is "primary" as every repository has the whole history, so you can recreate it every time something goes bad Oct 17, 2018 at 14:02
-
manual tagging or note-keeping is needed
, one option unless the repo is very big is:git bundle create my.bundle --all
, it should contain everything Oct 17, 2018 at 17:10 -
I like this answer more as it's more illustrative even though the accepted answer and this says the same thing.– RystraumOct 18, 2018 at 13:38
-
-
1It creates a repository that is just the database (what you'd normally find in the
.git/
hidden folder), without a 'working tree' (the editable files). It is the preferred form for repositories that yougit push
to. Oct 18, 2018 at 17:54
git bundle create
One of the methods is to use external storage to exchange data between repositories is git bundle. This way you only have single files for each transfer, not intermediate Git repositories.
Each "git push" turns into creation of a file, "git fetch" fetches things from that file.
Demo session
Creating the first repository and doing the first "push"
gitbundletest$ mkdir repo1
gitbundletest$ cd repo1
repo1$ git init
Initialized empty Git repository in /tmp/gitbundletest/repo1/.git/
repo1$ echo 1 > 1 && git add 1 && git commit -m 1
[master (root-commit) c8b9ff9] 1
1 file changed, 1 insertion(+)
create mode 100644 1
repo1$ git bundle create /tmp/1.bundle master HEAD
Enumerating objects: 3, done.
Counting objects: 100% (3/3), done.
Writing objects: 100% (3/3), 384 bytes | 384.00 KiB/s, done.
Total 3 (delta 0), reused 0 (delta 0)
"cloning" to the second repository (i.e. the second computer):
gitbundletest$ git clone /tmp/1.bundle repo2
Cloning into 'repo2'...
Receiving objects: 100% (3/3), done.
gitbundletest$ cd repo2/
repo2$ cat 1
1
Doing some changes and "pushing" them to another bundle file:
repo2$ echo 2 > 1 && git add 1 && git commit -m 2
[master 250d387] 2
1 file changed, 1 insertion(+), 1 deletion(-)
repo2$ git bundle create /tmp/2.bundle origin/master..master origin/HEAD..HEAD
Enumerating objects: 5, done.
Counting objects: 100% (5/5), done.
Writing objects: 100% (3/3), 415 bytes | 415.00 KiB/s, done.
Total 3 (delta 0), reused 0 (delta 0)
"pulling" changes to the first repository:
repo2$ cd ../repo1
repo1$ git pull /tmp/2.bundle
Receiving objects: 100% (3/3), done.
From /tmp/2.bundle
* branch HEAD -> FETCH_HEAD
Updating c8b9ff9..250d387
Fast-forward
1 | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
repo1$ cat 1
2
Unlike the first bundle, second one contains only partial Git history and is not directly clonable:
repo1$ cd ..
gitbundletest$ git clone /tmp/2.bundle repo3
Cloning into 'repo3'...
error: Repository lacks these prerequisite commits:
error: c8b9ff94942039469fa1937f6d38d85e0e39893a
fatal: bad object 250d38747656401e15eca289a27024c61e63ed68
fatal: remote did not send all necessary objects
There is disadvantage in using bundles that you need to manually specify what range of commits each bundle should contain. Unlike git push
, git bundle
does not keep track what was in previous bundle, you need to manually adjust refs/remotes/origin/master
or bundles would be bigger than it could be.
-
Don't forget to mention the
--all
flag to get everything. If the repo is small enough this is the simplest process as you simply transfer everything every time! Just don't loose the memory stick - probably the biggest security issue! Oct 19, 2018 at 11:08
You need to first install Git. Then to create a new repository, run within the folder that you've copied:
git init
Then you can add files you want to version control by git add
(add -a
for all files) and start committing the changes (git commit
).
You don't have to push to any remote, as you can work on your local history (git log
).
For more information, check:
Pushing/pulling without internet
Using git push
command, it's possible to push over SSH (using local connection, intranet):
git remote add server ssh://[user@]host.xz[:port]/path/to/dev/repo.git/
git push server
or pushing into the folder:
git push /mnt/usb/my_repo
This assumes you've two copies of your repository.
The same with pulling, e.g.
git pull /mnt/usb/my_repo
Patching
To apply patches, you can use patch
command or git apply
.
See: Create patch or diff file from git repository and apply it to another different git repository.
You can use Git locally too. Then your commits are only stored locally, and you still have version control with it (and can diff/merge etc.), but you just can't access the repository from any other computer.
You can start a local Git repository by running git init
in your local folder. As described here.
-
3that I know, but I want to work on another computer and apply it to files on server with no internet access Oct 17, 2018 at 11:46
-
2@TutuKaeen I see nothing wrong with having the repository on a flash drive and just cloning/syncing it to hard drives of different computers. However, "server without internet access" sounds strange, the goal of a server is to provide a service, most often the service is related to networking (but not always, indeed). Oct 17, 2018 at 13:11
-
2@dhae - Please take a moment to provide more details on how to use Git locally. Only indicating it can be done isn't that helpful of an answer.– RamhoundOct 17, 2018 at 13:32
-
2@anonymousLurker the serving is serving data to closed network in very important institution. It just doesn't serve anything to the broad internet, as the data is very delicate and for the employees only. Oct 17, 2018 at 14:05
-
1@TutuKaeen: If it has any network access, you could always run your own Git server via SSH. There's more to Git than just GitHub. Oct 17, 2018 at 15:17
server
for a machine not connected to any network. It could just be a local network even without internet access but it's still a network nonetheless.