題 在沒有網絡訪問的情況下跨多個系統使用Git


我想使用版本控制,但由於安全原因,我正在處理的服務器無法訪問互聯網:我只能在USB閃存盤上移動文件。我仍然可以使用Git進行此設置嗎?我可以創建可以在Git存儲庫上應用的小補丁嗎?


83
2017-10-17 11:39


起源


你的標題說沒有網絡訪問,你的問題說沒有互聯網接入;巨大的差異。 - tkausl
@TutuKaeen您可以擁有一個未連接到互聯網的本地網絡。而不是 github.com 你在例如設置git服務器。 192.168.1.100 其他一切都是一樣的。 - Agent_L
@TutuKaeen:關鍵問題是兩台機器之間是否可以進行直接(或間接)網絡通信。所以在你的情況下,兩台機器都是聯網的,但網絡是分開的?在這種情況下,請將該信息編輯到您的問題中。 - sleske
@TutuKaeen你的問題仍然不清楚。您說您想要使用版本控制,但在您的註釋中,您需要它可以幫助您部署到生產環境。這些問題並不總是重疊。我認為你現在有很好的答案,但是將來如果你的問題更全面地了解你的要求會有所幫助,這似乎是:“我想使用版本控制,我的開發機器沒有互聯網訪問,它確實有網絡訪問但不能訪問生產機器,我想知道如何將代碼從版本控制中提取到生產機器上。“ - DavidS
使用該術語似乎很奇怪 server 對於未連接到任何網絡的計算機。即使沒有互聯網接入,它也可能只是一個本地網絡,但它仍然是一個網絡。 - uom-pgregorio


答案:


當然,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將使用一些標準的網絡組件(與本地磁盤通信),這是較慢的。


155
2017-10-17 12:24



為了增加這個特殊的答案 - 使用閃存驅動器上的“裸”存儲庫進行調查可能也是值得的。 'bare'存儲庫沒有工作樹,因此在用作共享“權限”時會刪除一類潛在問題,這聽起來像OP的用例。 - Iron Gremlin
該 file:// 也有點靈活。它允許您使用一些您不能使用本地路徑的功能(如淺克隆)。 - Austin Hemmelgarn
@IronGremlin你能否擴展這個“共享的權威點”概念?我不是Git專家,我很好奇你的意思。 - Lightness Races in Orbit
@LightnessRacesinOrbit - 這是一個非常密集的主題,但基本上,git是分佈式的,所以每個人都有自己的歷史。 A可以向B詢問他們的歷史版本,但除非有人告訴他們,否則C不知道。擁有一個存儲“權威”歷史記錄的存儲庫意味著D充當歷史記錄的交換所。因此,A告訴D有關變化,B和C知道要與D交談以保持最新狀態,而不是在他們之間進行旁道通信。舉個例子,如果OP的服務器是C,並且閃存驅動器是D,它確保服務器不會被排除在A / B交互之外。 - Iron Gremlin
@LightnessRacesinOrbit這裡需要注意的是,裸不必具有權威性,它在這種情況下非常有用。例如,它也很有用,因為缺少工作樹,它是一個較小的磁盤空間(或帶寬)佔用空間。這曾經是比現在更重要的地獄,但仍然出現。 - Iron Gremlin


在一個  電腦,沒什麼特別需要的。跑 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,則可以執行此操作 與上述相同,只需使用指定SSH地址 [user@]host:path 要么 ssh://[user@]host/path 句法。

  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. 與上面相同。


46
2017-10-17 12:21



實際上它對我的目的來說並不壞,同樣在git中沒有什麼是“主要的”,因為每個存儲庫都有整個歷史記錄,所以你可以在每次出現問題時重新創建它 - Tutu Kaeen
manual tagging or note-keeping is needed,除非回購非常大,否則一個選擇是: git bundle create my.bundle --all,它應該包含一切 - birdspider
我更喜歡這個答案,因為它更具說明性,即使接受的答案和這說明了同樣的事情。 - Rystraum
“裸”選項有什麼意義? - Lightness Races in Orbit
它創建了一個存儲庫 只是 數據庫(你通常在 .git/ 隱藏文件夾),沒有“工作樹”(可編輯文件)。它是您的首選存儲庫形式 git push至。 - grawity


git bundle create

其中一種方法是使用外部存儲來在存儲庫之間交換數據 git捆綁。這樣,每次傳輸只有一個文件,而不是中間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

使用bundle需要手動指定每個bundle應包含的提交範圍。不像 git pushgit bundle 不跟踪先前捆綁中的內容,您需要手動調整 refs/remotes/origin/master 或捆綁將比它更大。


21
2017-10-17 15:33



別忘了提 --all 得到一切的旗幟。如果回購足夠小,這是最簡單的過程,因為您每次只需轉移所有內容!只是不要鬆開記憶棒 - 可能是最大的安全問題! - Philip Oakley


你需要先安裝 混帳。然後,要創建新的存儲庫,請在您複製的文件夾中運行:

git init

然後,您可以添加要進行版本控制的文件 git add (加 -a 對於所有文件)並開始提交更改(git commit)。

您無需推送任何遙控器,因為您可以處理當地歷史記錄(git log)。

有關更多信息,請檢查:


沒有互聯網推/拉

運用 git push 命令,可以推送SSH(使用本地連接,內聯網):

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

修補

要應用修補程序,您可以使用 patch 命令或 git apply

看到: 從git存儲庫創建補丁或差異文件,並將其應用到另一個不同的git存儲庫


7
2017-10-17 12:09





你也可以在本地使用Git。然後你的提交只存儲在本地,你仍然可以使用它進行版本控制(並且可以進行差異/合併等),但是你無法從任何其他計算機訪問存儲庫。

您可以通過運行來啟動本地Git存儲庫 git init 在您的本地文件夾中。 如此處所述


5
2017-10-17 11:43



我知道,但我想在另一台計算機上工作,並將其應用於服務器上沒有互聯網訪問權限的文件 - Tutu Kaeen
@TutuKaeen我認為在閃存驅動器上安裝存儲庫並將其克隆/同步到不同計算機的硬盤驅動器沒有任何問題。然而,“沒有互聯網接入的服務器”聽起來很奇怪,服務器的目標是提供服務,大多數情況下服務與網絡有關(但並非總是如此)。 - AnonymousLurker
@dhae - 請花點時間提供有關如何在本地使用Git的更多詳細信息。只表明可以做到這一點對答案沒有幫助。 - Ramhound
@anonymousLurker服務是在非常重要的機構向封閉網絡提供數據。它只是沒有為廣泛的互聯網提供任何服務,因為數據非常微妙,僅供員工使用。 - Tutu Kaeen
@TutuKaeen:如果有的話 任何 網絡訪問,你總是可以通過SSH運行自己的Git服務器。 Git不僅僅是GitHub。 - grawity