การใช้ 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สำหรับเครื่องที่ไม่ได้เชื่อมต่อกับเครือข่ายใด ๆ มันอาจเป็นเครือข่ายท้องถิ่นแม้ว่าจะไม่มีการเชื่อมต่ออินเทอร์เน็ต แต่ก็ยังคงเป็นเครือข่าย
uom-pgregorio

คำตอบ:


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ชี้ไปยังเซิร์ฟเวอร์อินเทอร์เน็ตที่อื่น):

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

จากนั้นคุณสามารถผลัก / ดึงไปยัง / จากรีโมทนี้เหมือนกัน

หากคุณอ่านเอกสารคุณจะสังเกตเห็นว่ามีfile://โปรโตคอลที่ทำงานแตกต่างกันเล็กน้อย ขอแนะนำให้ใช้เส้นทางในเครื่องเนื่องจากจะใช้ประโยชน์จากการเพิ่มประสิทธิภาพบางอย่าง - หากคุณใช้file://โปรโตคอลแล้ว git จะใช้ส่วนประกอบเครือข่ายมาตรฐานบางส่วน (เพื่อพูดคุยกับดิสก์ภายในเครื่อง) ซึ่งช้ากว่า


50
เพื่อเพิ่มคำตอบพิเศษนี้ - มันอาจคุ้มค่าที่จะตรวจสอบโดยใช้พื้นที่เก็บข้อมูล 'เปลือย' ในแฟลชไดรฟ์ ที่เก็บข้อมูลแบบ 'เปล่า' ไม่มีแผนผังการทำงานและตัดหมวดหมู่ของปัญหาที่อาจเกิดขึ้นเมื่อใช้เป็น 'จุดอำนาจ' ที่ใช้ร่วมกันซึ่งฟังดูเหมือนกรณีใช้งานของ OP
Iron Gremlin

5
file://นี้ยังมีความยืดหยุ่นมากขึ้นเล็กน้อย มันช่วยให้คุณใช้คุณสมบัติบางอย่าง (เช่นโคลนตื้น) ที่คุณไม่สามารถใช้กับเส้นทางท้องถิ่นได้
Austin Hemmelgarn

1
@IronGremlin คุณสามารถขยายความคิดในเรื่องนี้ ฉันไม่ใช่ผู้เชี่ยวชาญ Git และฉันอยากรู้ว่าคุณหมายถึงอะไร
การแข่งขัน Lightness ใน Orbit

2
@LightnessRacesinOrbit - นี่เป็นหัวข้อที่ค่อนข้างหนาแน่น แต่โดยทั่วไปแล้วคอมไพล์มีการแจกจ่ายดังนั้นทุกคนจึงได้รับประวัติของตัวเอง A สามารถถาม B เกี่ยวกับประวัติรุ่นของพวกเขาได้ แต่ C ไม่รู้เกี่ยวกับเรื่องนี้จนกว่าจะมีใครบอกพวกเขา การมีที่เก็บเดียวเพื่อเก็บประวัติ 'เผด็จการ' หมายถึง D ทำหน้าที่เป็นสำนักหักบัญชีสำหรับประวัติ ดังนั้น A จะบอก D เกี่ยวกับการเปลี่ยนแปลงและ B และ C รู้ที่จะพูดคุยกับ D เพื่อรับข้อมูลล่าสุดแทนที่จะทำสิ่งต่าง ๆ ในช่องทางระหว่างกัน ในกรณีที่จุดถ้าเซิร์ฟเวอร์ของ OP เป็น C และแฟลชไดรฟ์เป็น D ก็ทำให้แน่ใจว่าเซิร์ฟเวอร์ไม่ได้ออกจากการโต้ตอบ A / B
Iron Gremlin

6
@LightnessRacesinOrbit สิ่งสำคัญที่ควรทราบที่นี่ไม่จำเป็นต้องมีความหมายเปล่า ๆ มันเป็นเพียงประโยชน์ในบริบทนั้น ตัวอย่างเช่นมันยังมีประโยชน์เพราะขาดต้นไม้ที่ใช้งานได้มันเป็นพื้นที่ทำงานขนาดเล็ก (หรือแบนด์วิดท์) ที่เล็กลง สิ่งนี้เคยเป็นสิ่งที่มีความสำคัญมากกว่าตอนนี้ แต่ยังคงเกิดขึ้น
Iron Gremlin

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 ไว้คุณสามารถทำเช่นเดียวกันกับข้างต้นเพียงระบุที่อยู่ 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:คุณสามารถสร้าง 'โอนบันเดิล' ซึ่งเก็บรายการการคอมมิทที่กำหนดลงในไฟล์เดียว

น่าเสียดายที่คำสั่งบันเดิลจะไม่จดจำสิ่งที่รวมไว้เป็นครั้งสุดท้ายโดยอัตโนมัติดังนั้นจึงจำเป็นต้องติดแท็กด้วยตนเองหรือการเก็บบันทึกย่อ ฉันจะเอาตัวอย่างจากคู่มือ 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ตัวเลือกเดียวยกเว้น repo ที่มีขนาดใหญ่มากคือ: git bundle create my.bundle --allมันควรมีทุกอย่าง
birdspider

ฉันชอบคำตอบนี้มากขึ้นเพราะมันเป็นตัวอย่างที่ชัดเจนยิ่งขึ้นแม้ว่าคำตอบที่ได้รับการยอมรับและสิ่งนี้พูดในสิ่งเดียวกัน
Rystraum

ความสำคัญของตัวเลือก "เปลือย" คืออะไร
Lightness Races ในวงโคจร

1
มันสร้างพื้นที่เก็บข้อมูลที่เป็นเพียงฐานข้อมูล (สิ่งที่คุณมักจะพบใน.git/โฟลเดอร์ที่ซ่อนอยู่) โดยไม่ต้อง 'ต้นไม้ทำงาน' (ไฟล์ที่สามารถแก้ไขได้) มันเป็นรูปแบบที่ต้องการสำหรับที่เก็บข้อมูลที่คุณgit pushทำ
grawity

20

git bundle create

หนึ่งในวิธีการที่จะใช้จัดเก็บข้อมูลภายนอกในการแลกเปลี่ยนข้อมูลระหว่างเก็บเป็นกำคอมไพล์ วิธีนี้คุณมีไฟล์เดียวสำหรับการถ่ายโอนแต่ละครั้งไม่ใช่ที่เก็บ Git ระดับกลาง

แต่ละ "git push" จะเปลี่ยนเป็นการสร้างไฟล์ "git fetch" ดึงสิ่งต่าง ๆ จากไฟล์นั้น

เซสชั่นการสาธิต

สร้างพื้นที่เก็บข้อมูลแรกและทำการ "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)

"การโคลน" ไปยังที่เก็บข้อมูลที่สอง (เช่นคอมพิวเตอร์เครื่องที่สอง):

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)

"pulling" เปลี่ยนเป็นที่เก็บแรก:

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 push, git bundleไม่ได้ติดตามสิ่งที่อยู่ในห่อก่อนหน้านี้คุณจำเป็นต้องปรับด้วยตนเองrefs/remotes/origin/masterหรือการรวมกลุ่มจะมีขนาดใหญ่กว่ามันอาจจะเป็น


อย่าลืมพูดถึง--allธงเพื่อรับทุกสิ่ง ถ้า repo มีขนาดเล็กพอนี่เป็นกระบวนการที่ง่ายที่สุดเพราะคุณโอนทุกอย่างทุกครั้ง! อย่าทำให้เมมโมรี่สติ๊กหลวม - อาจเป็นปัญหาด้านความปลอดภัยที่ใหญ่ที่สุด!
Philip Oakley

7

คุณต้องติดตั้งGitก่อน จากนั้นเพื่อสร้างที่เก็บใหม่ให้เรียกใช้ภายในโฟลเดอร์ที่คุณคัดลอก:

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

ปะ

เมื่อต้องการใช้แพทช์, คุณสามารถใช้คำสั่งหรือpatchgit apply

ดู: สร้างแพทช์หรือไฟล์ต่างจากพื้นที่เก็บข้อมูลคอมไพล์และนำไปเก็บคอมไพล์อื่นที่แตกต่างกัน


5

คุณสามารถใช้ Git ภายในเครื่องได้เช่นกัน จากนั้นคอมมิทของคุณจะถูกเก็บไว้ในเครื่องเท่านั้นและคุณยังสามารถควบคุมเวอร์ชันได้ (และสามารถกระจาย / รวม ฯลฯ ) แต่คุณไม่สามารถเข้าถึงที่เก็บจากคอมพิวเตอร์เครื่องอื่น ๆ

คุณสามารถเริ่มต้นที่เก็บ Git ในเครื่องได้โดยการเรียกใช้git initในโฟลเดอร์ท้องถิ่นของคุณ ตามที่อธิบายไว้ที่นี่


3
ที่ฉันรู้ แต่ฉันต้องการที่จะทำงานบนคอมพิวเตอร์เครื่องอื่นและนำไปใช้กับไฟล์บนเซิร์ฟเวอร์ที่ไม่มีการเข้าถึงอินเทอร์เน็ต
ตูตู Kaeen

2
@TutuKaeen ฉันเห็นว่าไม่มีอะไรผิดปกติกับการมีพื้นที่เก็บข้อมูลในแฟลชไดรฟ์และเพียงแค่โคลน / ซิงค์กับฮาร์ดไดรฟ์ของคอมพิวเตอร์ที่แตกต่างกัน อย่างไรก็ตาม "เซิร์ฟเวอร์ที่ไม่มีอินเทอร์เน็ต" ฟังดูไม่ดีเป้าหมายของเซิร์ฟเวอร์คือการให้บริการส่วนใหญ่มักจะเกี่ยวข้องกับบริการเครือข่าย (แต่ไม่เสมอไป)
AnonymousLurker

2
@dhae - โปรดสละเวลาสักครู่เพื่อให้รายละเอียดเพิ่มเติมเกี่ยวกับวิธีการใช้ Git ในเครื่อง การระบุว่าสามารถทำได้เท่านั้นไม่ได้มีประโยชน์สำหรับคำตอบ
Ramhound

2
@anonymousLurker การให้บริการกำลังให้บริการข้อมูลกับเครือข่ายที่ปิดในสถาบันที่สำคัญมาก มันไม่ได้ให้บริการอะไรกับอินเทอร์เน็ตในวงกว้างเนื่องจากข้อมูลมีความละเอียดอ่อนมากและสำหรับพนักงานเท่านั้น
Tutu Kaeen

1
@TutuKaeen: หากมีการเข้าถึงเครือข่ายใด ๆคุณสามารถเรียกใช้เซิร์ฟเวอร์ Git ของคุณเองผ่าน SSH มีมากกว่า Git มากกว่าแค่ GitHub
grawity
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.