在没有网络访问的情况下跨多个系统使用Git


84

我想使用版本控制,但是由于安全原因,我正在使用的服务器无法访问互联网:我只能在USB闪存驱动器上移动文件。我仍然可以在此设置中使用Git吗?我可以创建可应用于Git存储库的小补丁吗?


65
您的标题说没有网络访问,您的问题说没有互联网访问;巨大的差异。
tkausl

7
@TutuKaeen您可以拥有未连接到互联网的本地网络。因此,您无需在github.com上设置git服务器,例如。192.168.1.100,其他所有功能都相同。
Agent_L

12
@TutuKaeen:关键问题是两台机器之间是否可以进行直接(或间接)网络通信。那么在您的情况下,两台计算机都已联网,但网络是分开的吗?在这种情况下,请将该信息编辑为您的问题。
sleske

15
@TutuKaeen您的问题仍然不清楚。您说要使用版本控制,但在注释中需要使用它来帮助您部署到生产环境。这些问题并不总是重叠的。我认为您现在在下面有很好的答案,但是将来,如果您的问题更全面地了解您的要求,这似乎会有所帮助,这似乎是:“我想使用版本控制,我的开发机无法访问互联网,它确实具有网络访问权,但不能访问生产机器,我想知道如何从版本控制中获取代码到生产机器上。”
DavidS

4
server对于未连接任何网络的机器使用该术语似乎很奇怪。即使没有互联网,它也可能只是一个本地网络,但它仍然是一个网络。
帕特里克·格雷戈里奥

Answers:


157

当然,关于Git的任何事情都不需要特定的协议。刚刚开箱的标准客户端支持 HTTP(S),SSH,自定义Git协议和,重要的是,当地的协议。尽管命名只是一个约定,但这只需要指向本地.git目录的路径,该目录可以位于工作目录(/path/to/project/.git)内,也可以位于裸目录(/path/to/project.git)内。

当然,这意味着您可以将闪存驱动器添加为遥控器:

git remote add origin /mnt/flashdrive/foo.git

或者,在Windows上:

git remote add origin F:\foo.git

甚至将其添加为其他名称的远程(如果您希望origin指向某处的Internet服务器):

git remote add flashdrive /mnt/flashdrive/foo.git

然后,您就可以像其他遥控器一样将其推入/拉出遥控器。

如果您阅读了文档,您会发现还有一个file://协议的行为略有不同。建议使用本地路径,因为这将利用一些其他优化方法-如果您使用file://协议,则git将使用一些标准的网络组件(与本地磁盘通信),这比较慢。


50
要增加这个例外答案-使用闪存驱动器上的“裸机”存储库进行调查可能也值得。“裸”存储库没有工作树,因此当用作共享的“授权点”时,可以切出一类潜在的问题,这听起来像是OP的用例。
Iron Gremlin '18

5
file://也更灵活一点。它允许您使用本地路径无法使用的某些功能(例如浅克隆)。
奥斯汀·海默加恩

1
@IronGremlin您能否扩展这个“共享权限点”概念?我不是Git专家,我很好奇您的意思。
Lightness Races in Orbit

2
@LightnessRacesinOrbit-这是一个非常密集的话题,但是,基本上,git是分布式的,所以每个人都有自己的历史。A可以向B询问他们的历史版本,但是C除非有人告诉他们,否则不知道。具有单个存储“权威”历史记录的存储库意味着D充当历史记录的交换所。因此,A告诉D了有关更改的信息,而B和C知道与D保持最新联系,而不是在他们中间做旁道工作。举例来说,如果OP的服务器为C,而闪存驱动器为D,则可以确保服务器不会被A / B交互所影响。
Iron Gremlin '18

6
@LightnessRacesinOrbit在这里需要特别注意的是,裸露不一定意味着权威,它只是在这种情况下有用。例如,它也很有用,因为缺少可用的树,它的磁盘空间(或带宽)占用空间较小。这曾经比现在要重要得多,但是仍然存在。
Iron Gremlin '18

46

台计算机上,不需要任何特殊设置。git init在您需要的目录中运行,并像往常一样使用Git。

为了在台计算机之间同步存储库,有几种方法。

方法1a(根本没有网络):您可以在USB记忆棒上创建一个“裸存储库”,然后将其推入并从中拉出,就像使用其他远程存储库一样。换句话说,通过本地路径进行的存储库操作与通过SSH或HTTPS URL进行的操作没有什么不同。

  1. 创建一个“远程”存储库:

    $ git init --bare /mnt/Stick/Repositories/Large_Project.git
    
  2. 在计算机1中,将所有内容推送到其中:

    $ cd ~/Large_Project
    $ git remote add usb /mnt/Stick/Repositories/Large_Project.git
    $ git push usb master
    
  3. 在计算机2中,一如既往。

    $ git remote add usb /mnt/Stick/Repositories/Large_Project.git
    $ git pull usb
    

(您也可以直接从URL或路径推/获取/拉。)

方法1b(内部网络):如果您的内部服务器具有SSH,并且安装了Git,则可以执行上述操作,只需使用[user@]host:pathssh://[user@]host/path语法指定SSH地址即可。

  1. 通过git init --bare <somepath.git>在指定服务器上运行(通过SSH)来创建“远程”存储库。

  2. 在计算机1中,方法与前面演示的相同。

    $ git remote add origin myserver.example.com:Gits/Large_Project.git
    

    或者,如果您喜欢:

    $ git remote add origin ssh://myserver.example.com/Gits/Large_Project.git
    
  3. 在计算机2中,再次与方法1a相同。


方法2:您可以创建“传输捆绑包”,将给定的提交列表存档到单个文件中。

不幸的是,bundle命令不能自动记住上次已捆绑的内容,因此需要手动标记或记笔记。我将仅从git-bundle手册中获取示例。

  1. 在计算机1中,创建整个分支的捆绑包:

    $ cd ~/Large_Project
    $ git bundle create /mnt/Stick/Project.bundle master
    $ git tag -f last-bundled master
    
  2. 在计算机2中,将其作为存储库从捆绑软件中拉出:

    $ cd ~/Large_Project
    $ git pull /mnt/Stick/Project.bundle
    

随后的捆绑包不需要打包整个master包,last-bundled..master而是可以打包来自其中的新添加的提交。

  1. 在计算机1中,创建一包新添加的提交:

    $ cd ~/Large_Project
    $ git bundle create /mnt/Stick/Project.bundle last-bundled..master
    $ git tag -f last-bundled master
    
  2. 同上。


实际上,这对我来说不是一件坏事,而且在git中,每个仓库都具有完整的历史记录,所以“主要”是什么,所以每次出现问题时都可以重新创建它
Tutu Kaeen

manual tagging or note-keeping is needed,除非回购协议非常庞大,否则一种选择是:git bundle create my.bundle --all,其中应包含所有内容
Birdpider

我更喜欢这个答案,因为即使被接受的答案也是如此,但它更具说明性。
Rystraum

“裸”选项的意义是什么?
Lightness Races in Orbit 18'18

1
它创建的存储库只是数据库(通常会在.git/隐藏文件夹中找到),而没有“工作树”(可编辑文件)。这是您git push要使用的存储库的首选形式。
grawity

20

git bundle create

一种方法是使用外部存储在存储库之间交换数据,即git bundle。这样,每次传输您只有单个文件,而没有中间的Git存储库。

每次“ git push”都会创建一个文件,“ git fetch”会从该文件中获取内容。

示范会议

创建第一个存储库并执行第一个“推送”

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)

“克隆”到第二个存储库(即第二台计算机):

gitbundletest$ git clone /tmp/1.bundle repo2
Cloning into 'repo2'...
Receiving objects: 100% (3/3), done.

gitbundletest$ cd repo2/

repo2$ cat 1
1

进行一些更改,然后将其“推”到另一个捆绑文件中:

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)

“拉”对第一个存储库的更改:

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

与第一个捆绑包不同,第二个捆绑包仅包含部分Git历史记录,并且不能直接克隆:

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

使用捆绑软件有一个缺点,您需要手动指定每个捆绑软件应包含的提交范围。与不同的是git pushgit bundle它不会跟踪先前捆绑软件中的内容,因此您需要手动进行调整,refs/remotes/origin/master否则捆绑软件会变得更大。


不要忘记提到--all标志以获取所有内容。如果仓库足够小,这是最简单的过程,因为您每次都只需传输所有内容!只是不要松开记忆棒-可能是最大的安全问题!
菲利普·奥克利

7

您需要先安装Git。然后,要创建新的存储库,请在复制的文件夹中运行:

git init

然后,您可以添加要进行版本控制的文件git add-a为所有文件添加),然后开始提交更改(git commit)。

您无需推送到任何远程设备,因为您可以处理本地历史记录(git log)。

有关更多信息,请检查:


没有互联网的推/拉

使用git push命令,可以推送SSH(使用本地连接,Intranet):

git remote add server ssh://[user@]host.xz[:port]/path/to/dev/repo.git/
git push server

或推入文件夹:

git push /mnt/usb/my_repo

假设您有存储库的两个副本。

拉动也一样,例如

git pull /mnt/usb/my_repo

打补丁

要应用补丁,您可以使用patchcommand或git apply

请参阅:从git仓库创建补丁或diff文件,并将其应用于另一个不同的git仓库


5

您也可以在本地使用Git。然后,您的提交仅存储在本地,并且仍具有版本控制(并且可以进行diff /合并等),但是您无法从任何其他计算机访问存储库。

您可以通过git init在本地文件夹中运行来启动本地Git存储库。如此处所述


3
我知道,但是我想在另一台计算机上工作并将其应用于无法访问互联网的服务器上的文件
Tutu Kaeen 18-10-17

2
@TutuKaeen我认为将存储库放在闪存驱动器上并将其克隆/同步到不同计算机的硬盘驱动器上没有什么错。但是,“无法访问Internet的服务器”听起来很奇怪,服务器的目标是提供一项服务,大多数情况下,该服务与联网有关(但并非总是如此)。
AnonymousLurker

2
@dhae-请花一点时间提供有关如何在本地使用Git的更多详细信息。仅指出可以完成并没有帮助答案。
Ramhound

2
@anonymousLurker服务正在非常重要的机构中向封闭的网络提供数据。它对宽带互联网毫无用处,因为数据非常微妙,仅适用于员工。
Tutu Kaeen

1
@TutuKaeen:如果可以访问任何网络,则可以始终通过SSH运行自己的Git服务器。Git不仅有GitHub,还有更多。
grawity
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.