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?
-
65Your title says no network access, your question says no internet access; a huge difference. – tkausl Oct 18 '18 at 04:18
-
what's the difference in the context of the question? I cannot pull changes from usb stick only as I work on the machine that is not connected to the machine I'm deploying to. Now I'm doing it by copying unversioned files, as did the developers before me. I want to change that workflow and that's all. – Zbyszek Kisły Oct 18 '18 at 08:59
-
7@TutuKaeen You can have a local network that's not connected to the internet. So instead of https://github.com you set up git server at eg. https://192.168.1.100 and everything else works same. – Agent_L Oct 18 '18 at 09:03
-
1why would I do that? Machine I'm working on still is not connected to the machine I'm deploying, if I have additional repo in the local network I need to push from flash drive to local network repository and pull to production. As I understood I can do that directly from flash drive, so what's the advantage of adding additional step? – Zbyszek Kisły Oct 18 '18 at 09:30
-
12@TutuKaeen: The critical question is whether direct (or indirect) network communication is possible between the two machines. So in your case, both machines are networked, but the networks are separated? In that case, please edit that information into your question. – sleske Oct 18 '18 at 12:14
-
15@TutuKaeen Your question remains unclear. You say you want to use version control, but in your comments you require that it help you deploy to production. These issues don't always overlap. I think you have good answers below now, but in the future it would be helpful if your question were more comprehensive about your requirements, which seem to be: "I want to use version control, my development machine doesn't have internet access, it does have network access but not to the production machine, and I want to know how to get code out of version control onto the production machine." – DavidS Oct 18 '18 at 16:46
-
4It just seems weird to use the term `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. – dokgu Oct 18 '18 at 20:00
-
1`git bundle --all` is a good place to start – Philip Oakley Oct 19 '18 at 11:09
-
IIRC, moving patches around off-line via removable media was one of Git's original designed use-cases. – T.E.D. Oct 22 '18 at 16:36
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.
- 12,090
- 23
- 70
- 90
- 60,938
- 25
- 191
- 216
-
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. – Iron Gremlin Oct 17 '18 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. – Austin Hemmelgarn Oct 17 '18 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. – Lightness Races in Orbit Oct 18 '18 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. – Iron Gremlin Oct 18 '18 at 17:58
-
@IronGremlin Okay, interesting, and I think I get it. IMO the terminology threw me off a bit - although I now understand why they're called "bare" (no working tree) the core use case seems to be as a different class of repo, a sort of "god" or "root" repo which clones ought to look up to. I don't know what else I'd call such a repo but I'm not sure "bare" is the clearest. Then again it describes what it _is_ rather than how people use it so maybe that's all we need :) Anyway, thanks for the explanation! – Lightness Races in Orbit Oct 18 '18 at 18:09
-
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. – Iron Gremlin Oct 18 '18 at 18:12
-
-
@AustinHemmelgarn Probably because there is no point to shallow clones on local paths. Git optimizes it by using hard-links instead of file copies. A full deep clone doesn't use any extra disk space. – Zan Lynx Oct 19 '18 at 22:31
-
@ZanLynx Hard links only apply to local paths on the same filesystem, which is definitely not the case here. But in general, getting hardlinks to stay put is very finicky for files that are being actively created or deleted, such as with git's packing. (Thus, the need for [git-relink](https://git-scm.com/docs/git-relink) exists to overcome this limitation.) – jpaugh Oct 21 '18 at 16:55
-
@ZanLynx Hard links don't always work as expected, and you obviously can't use them if you're cloning to a different filesystem. Additionally, ensuring that you can't accidentally push while still being able to pull updates is a nice safety net to have (though there would ideally be better ways to do it). – Austin Hemmelgarn Oct 22 '18 at 12:42
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.gitIn computer 1, push everything to it:
$ cd ~/Large_Project $ git remote add usb /mnt/Stick/Repositories/Large_Project.git $ git push usb masterIn 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.gitOr if you prefer:
$ git remote add origin ssh://myserver.example.com/~/Gits/Large_Project.gitIn 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 masterIn 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 masterSame as above.
- 426,297
- 64
- 894
- 966
-
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 – Zbyszek Kisły Oct 17 '18 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 – birdspider Oct 17 '18 at 17:10
-
I like this answer more as it's more illustrative even though the accepted answer and this says the same thing. – Rystraum Oct 18 '18 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 you `git push` to. – u1686_grawity Oct 18 '18 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.
- 16,755
- 32
- 111
- 189
-
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! – Philip Oakley Oct 19 '18 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.
- 24,736
- 27
- 129
- 199
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.
- 12,090
- 23
- 70
- 90
- 65
- 3
-
3that I know, but I want to work on another computer and apply it to files on server with no internet access – Zbyszek Kisły Oct 17 '18 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). – AnonymousLurker Oct 17 '18 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. – Ramhound Oct 17 '18 at 13:32
-
@Ramhound Is it better like that? And should i delete my answer since there are answers that add much more and describe it better? Or is that not a thing to do in StackExchange? – dhae Oct 17 '18 at 13:48
-
Answer authors should be given every opportunity to improved their answer before it is deleted. – Ramhound Oct 17 '18 at 13:53
-
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. – Zbyszek Kisły Oct 17 '18 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. – u1686_grawity Oct 17 '18 at 15:17