ฉันสามารถจัดเก็บโฟลเดอร์. git นอกไฟล์ที่ฉันต้องการติดตามได้หรือไม่


147

ฉันมีความคิดที่ผิดปกติในการใช้คอมไพล์เป็นระบบสำรองข้อมูล ดังนั้นสมมติว่าฉันมีไดเรกทอรี. สำรองข้อมูล / ฉันและฉันต้องการสำรองข้อมูลโดยใช้ git เพื่อรักษาความสะอาดฉันไม่ต้องการมีไดเรกทอรี. git ในโฟลเดอร์ myfiles ดังนั้นฉันคิดว่าฉันสามารถสร้าง. /backup/git_repos/myfiles ได้ จากการดูเอกสาร git ฉันได้ลองทำสิ่งนี้:

$ cd backup/myfiles
$ mkdir ../git_repos/myfiles
$ git --git-dir=../git_repos/myfiles init
Initialized empty Git repository in backup/git_repos/myfiles/
$ git --git-dir="../git_repos/myfiles/" add foo
fatal: pathspec 'foo' did not match any files

คุณสามารถเห็นข้อความแสดงข้อผิดพลาดที่ฉันไปถึงที่นั่น ผมทำอะไรผิดหรือเปล่า?


9
เช่นเดียวกับแนวคิดการสำรองข้อมูลของคุณสิ่งนี้สามารถใช้เพื่อเก็บ "dotfiles" (.bashrc, .vimrc ฯลฯ ) ไว้ในโฮมไดเร็กตอรี่ขณะที่ยังคงอยู่ในโฟลเดอร์. git ที่อื่น
Philip

6
คำตอบที่ตรงไปตรงมามากที่สุด: stackoverflow.com/a/19548676/170352 (ฝังเพราะ upvotes เก่า)
แบรนดอน Bertelsen

1
ในกรณีที่คุณมีสิทธิ์ในการเขียนหรือไม่ต้องการที่จะทำการเปลี่ยนแปลงใด ๆ ไปยังไดเรกทอรีการทำงาน (เช่นการเพิ่ม .git / ฯลฯ ) นี้คำตอบด้านล่างโดยสิงห์ (ยังฝังอยู่ upvotes เก่า) ที่ดีที่สุดคือ
KobeJohn

1
@Philip ยกเว้นว่าที่เก็บ dotfiles ของคุณมี God submodules ด้วย Git ไม่รองรับ submodules ร่วมกับแผนผังงานภายนอก
maxschlepzig

คำตอบ:


101
git --git-dir=../repo --work-tree=. add foo

สิ่งนี้จะทำในสิ่งที่คุณต้องการ แต่จะดูดอย่างเห็นได้ชัดเมื่อคุณต้องระบุด้วยคำสั่ง git ทุกครั้งที่คุณใช้

คุณสามารถส่งออกGIT_WORK_TREE=.และGIT_DIR=../backupGit จะรับพวกเขาในแต่ละคำสั่ง ซึ่งจะช่วยให้คุณสามารถทำงานในที่เก็บเดียวต่อเชลล์ได้อย่างสะดวกสบายเท่านั้น

ฉันอยากจะแนะนำให้เชื่อมโยงไดเรกทอรี. git กับที่อื่นหรือสร้าง symlink ไปยังไดเรกทอรี. git จากไดเรกทอรีสำรองหลักของคุณ


1
คุณสามารถเก็บถาวรได้โดยไม่ต้องระบุ git-dir และแผนผังต้นไม้ในทุกคำสั่งและไม่มีลิงก์สัญลักษณ์ใด ๆ ดูคำตอบของฉัน
นิกส์

ข้อเสียของ symlink ก็คือมันมีอยู่ในแผนผังการทำงานและหากกระบวนการอื่น ๆ ลบล้างแผนผังการทำงานออกคุณก็สูญเสีย symlink ไปแล้ว
Jeff

นอกจากนี้หาก OP ไม่ต้องการไดเรกทอรีย่อย. git ในแผนผังการทำงานของเขาทำไมเขาถึงต้องการ symlink
Jeff

@Jeff: สำหรับการแลกเปลี่ยน (ในกรณีสำรองของเขาการเช็ดต้นไม้ที่ทำงานของเขานั้นอาจไม่น่าเป็นห่วงสำหรับเขามากกว่าเช็ดออก dir อื่น ๆ (เช่น repo เอง))
Sz.

1
ฉันใช้สิ่งนี้พร้อมกับdirenvสำหรับบันทึกของฉัน แผนผังการทำงานของฉันอยู่ในโฟลเดอร์ใน Dropbox และโฟลเดอร์คอมไพล์ของฉันอยู่ด้านนอก วิธีนี้ฉันสามารถเปลี่ยนแปลงคอมพิวเตอร์ทุกเครื่องได้อย่างง่ายดาย แต่ยังสามารถตรวจสอบสิ่งที่เปลี่ยนแปลงและกระทำเมื่อสิ่งที่สำคัญเปลี่ยนไปเท่านั้น ขอบคุณ
เปาโล Phagula

170

คุณเพียงแค่ต้องแน่ใจว่าที่เก็บรู้ว่าต้นไม้ทำงานอยู่ที่ไหนและในทางกลับกัน

core.worktreeเพื่อให้ความรู้ในพื้นที่เก็บข้อมูลที่ต้นไม้การทำงานคือการตั้งค่าการกำหนดค่า หากต้องการให้แผนผังการทำงานทราบว่าเป็นไดเรกทอรี git ใดให้เพิ่มไฟล์ชื่อ. git (ไม่ใช่โฟลเดอร์!) และเพิ่มบรรทัดเช่น

gitdir: /path/to/repo.git

ตั้งแต่ git 1.7.5 คำสั่ง init ได้เรียนรู้ตัวเลือกเพิ่มเติมสำหรับสิ่งนี้

คุณสามารถเริ่มต้นพื้นที่เก็บข้อมูลใหม่แยกด้วย

git init --separate-git-dir /path/to/repo.git

สิ่งนี้จะเริ่มต้นที่เก็บ git ในไดเรกทอรีแยกและเพิ่มไฟล์. git ในไดเรกทอรีปัจจุบันซึ่งเป็นไดเรกทอรีทำงานของที่เก็บใหม่

ก่อนหน้า 1.7.5คุณต้องใช้พารามิเตอร์ที่แตกต่างกันเล็กน้อยและเพิ่มไฟล์. git ด้วยตัวคุณเอง

ในการเริ่มต้นที่เก็บแยกต่างหากคำสั่งต่อไปนี้จะเชื่อมโยงแผนผังต้นไม้กับที่เก็บ:

git --git-dir=/path/to/repo.git --work-tree=. init && echo "gitdir: /path/to/repo.git" > .git

/path/to/repo.gitไดเรกทอรีปัจจุบันของคุณจะเป็นต้นไม้ที่ทำงานและการคอมไพล์จะใช้พื้นที่เก็บข้อมูลที่ คำสั่ง init จะตั้งค่าโดยอัตโนมัติcore.worktreeตามที่ระบุไว้กับ--git-dirพารามิเตอร์

คุณสามารถเพิ่มชื่อแทนสำหรับสิ่งนี้:

[alias]
    initexternal = !"f() { git --work-tree=. --git-dir=\"$1\" init && echo \"gitdir: $1\" >> .git; }; f"

ใช้การควบคุมเวอร์ชัน git ในไดเรกทอรีการทำงานแบบอ่านอย่างเดียว

ด้วยความรู้ด้านบนคุณสามารถตั้งค่าการควบคุมเวอร์ชัน git สำหรับไดเรกทอรีทำงานโดยไม่ต้องมีสิทธิ์ในการเขียน หากคุณใช้--git-dirกับทุกคำสั่ง git หรือดำเนินการทุกคำสั่งจากภายในที่เก็บข้อมูล (แทนไดเรกทอรีทำงาน) คุณสามารถออกจากไฟล์. git และไม่จำเป็นต้องสร้างไฟล์ใด ๆ ภายในไดเรกทอรีการทำงาน เห็นด้วยคำตอบ Leos


7
คุณสามารถทำเช่นนี้กับ repo ที่มีอยู่ได้ด้วย: ย้ายโฟลเดอร์. git ไปที่ใดก็ได้ที่คุณต้องการเพิ่มไฟล์. git เพื่อชี้ไปที่มันจากนั้นคุณก็สามารถใช้ repo ได้ตามปกติ
joachim

โปรดทราบว่าคุณสามารถออกคำสั่ง git จากรูท repo ของคุณเท่านั้น การเข้าไปในโฟลเดอร์ย่อยทำให้สับสน! (สิ่งนี้เกิดขึ้นไม่ว่าค่า gitdir ที่กำหนดนั้นจะสัมพันธ์กันหรือสัมบูรณ์)
joachim

2
การแก้ไขสำหรับสิ่งนี้คือการระบุ 'core.worktree' ในไฟล์ git config ที่แท้จริงเช่นที่อยู่ในโฟลเดอร์ที่คุณชี้ไปที่. git
joachim

2
ใช่นั่นคือสิ่งที่ฉันอธิบายในประโยคที่สองของคำตอบ core.worktreeแน่นอนว่าค่าการกำหนดค่าถูกเก็บไว้ในไฟล์กำหนดค่าของโฟลเดอร์. git ซึ่งไฟล์. git ชี้ไปที่
niks

1
fatal: core.worktree and core.bare do not make senseผมพบว่าเมื่อใช้คำแนะนำเหล่านี้ได้รับการซื้อคืนทำให้กลายเป็นพื้นที่เก็บข้อมูลเปลือยและมันจะช่วยให้ข้อผิดพลาด ดูเหมือนว่าเพียงแค่เปลี่ยนการกำหนดค่าดังนั้นจึงไม่ได้ช่วยแก้ไขปัญหานั้น
Steven Lu

62

--separate-git-dirตัวเลือกสำหรับการgit init(และgit clone) สามารถนำมาใช้เพื่อให้บรรลุนี้ในรุ่นของฉันคอมไพล์ ( 1.7.11.3) ตัวเลือกจะแยกที่เก็บ git ออกจากแผนผังการทำงานและสร้างลิงก์สัญลักษณ์ระบบ git ที่ไม่เชื่อเรื่องพระเจ้า (ในรูปแบบของชื่อไฟล์.git) ในรูทของแผนผังการทำงาน ฉันคิดว่าผลลัพธ์จะเหมือนกับคำตอบของนิก

git init --separate-git-dir path/to/repo.git path/to/worktree

2
+1 การใช้ตัวเลือกบรรทัดคำสั่งสำหรับinitตัวเองจะดูชัดเจนและสะอาดขึ้น
goncalopp

ใน windows repo.gitถูกสร้างขึ้นด้วยชุดแอตทริบิวต์ hiden ฉันเปลี่ยนมันเอง คุณรู้หรือไม่ว่าสิ่งนี้ปลอดภัยหรือไม่?
PA

+1 ใช่คอมไพล์ตัวเลือกบรรทัดคำสั่งนี้ในรุ่น 1.7.5 ซึ่งไม่สามารถใช้งานได้ในตอนนั้น (ถ้าฉันจำได้ถูกต้อง) ฉันได้อัพเดตคำตอบของฉันเพื่อแนะนำให้ใช้พารามิเตอร์นี้
niks

25

ฉันคิดว่ามันง่ายกว่าที่จะย้อนกลับ--work-treeและ--git-dirไดเรกทอรีที่ใช้ในคำตอบของ niks:

$ cd read_only_repos
$ git --work-tree=/some/readonly/location/foo/ --git-dir=foo init
$ cd foo
$ git status
On branch master

Initial commit

Untracked files:
  (use "git add <file>..." to include in what will be committed)

        .file_foo
        bar
        ...

วิธีนี้มีข้อดีสองประการ:

  • มันไม่จำเป็นต้องมีตัวเลือกบรรทัดคำสั่งหรือ.gitไฟล์ใด ๆ คุณทำงานตามปกติจากภายในรูทของที่เก็บ
  • อนุญาตให้คุณสร้างระบบไฟล์เวอร์ชันแม้ว่าคุณจะไม่ได้เป็นเจ้าของมัน Git จะเขียนไปยังตำแหน่งที่เก็บเท่านั้น

ข้อแม้เดียวที่ฉันได้พบก็คือว่าแทนการใช้แฟ้มคุณแก้ไข.gitignoreinfo/exclude

คุณสามารถใช้ที่เก็บread_only_repos/fooเป็นรีโมตในที่เก็บของคุณเองแม้ว่าไฟล์ต้นฉบับจะไม่อยู่ภายใต้การควบคุมเวอร์ชัน


ตรงนี้เป็นคำสั่งเดียวกันทั้งหมด ความแตกต่างเพียงอย่างเดียวที่ฉันเห็นก็คือคุณสลับลำดับของ - ข้อโต้แย้งต้นไม้ - และ - อาร์กิวเมนต์ -dit และนอกหลักสูตรคุณจะไม่สร้างไฟล์. git ในไดเรกทอรีการทำงานเนื่องจากคุณไม่มีสิทธิ์ในการเขียน อย่างไรก็ตามการใช้การควบคุมเวอร์ชันสำหรับไดเรกทอรีที่ไม่มีสิทธิ์การเขียนเป็นกรณีใช้งานที่ดี :-)
niks

3
คุณได้รับมัน กุญแจสำคัญคือการสร้าง repo นอกไดเรกทอรีทำงาน
Leo

4
ฉันชอบสิ่งนี้ - ช่วยให้ฉันสามารถใช้คอมไพล์ในไดเรกทอรีที่ฉันแบ่งปันกับ Dropbox ได้โดยไม่ต้องมีผู้เข้าร่วมคนอื่นแม้แต่รู้ว่ามีการใช้คอมไพล์อยู่
Quentin Stafford-Fraser

19

เป็นเรื่องธรรมดาที่จะตั้งชื่อไดเรกทอรีที่เป็นที่เก็บ git ที่มีแผนผังการทำงานในสถานที่ที่ผิดปกติพร้อมกับส่วนขยาย '.git' ซึ่งคล้ายกับที่เก็บเปลือย

mkdir ../git_repos/myfiles.git

หากคุณมี--work-treeตัวเลือกในเวลาเริ่มต้นสิ่งนี้จะมีการตั้งค่าcore.worktreeตัวแปรกำหนดค่าโดยอัตโนมัติซึ่งหมายความว่า git จะรู้ตำแหน่งที่จะหาแผนผังการทำงานเมื่อคุณระบุไดเรกทอรี git

git --git-dir=../git_repos/myfiles.git --work-tree=. init

แต่คุณสามารถตั้งค่าตัวแปรนี้หลังจากข้อเท็จจริงเช่นกัน

git --git-dir=../git_repos/myfiles.git config core.worktree "$(pwd)"

เมื่อคุณทำสิ่งนี้แล้วคำสั่งเพิ่มควรทำงานได้ตามที่คาดไว้

git --git-dir=../git_repos/myfiles.git add foo

ฉันพบถ้าคุณ cd to ../git_repos/myfiles.git ก่อนแทนที่จะอยู่ในแผนผังการทำงานจริง 'git add foo' จะใช้งานได้และคุณไม่จำเป็นต้องระบุ --git-dir ทั้งหมด เวลา.
Steve Folly

1
เป็นเรื่องจริง แต่ฉันคิดว่าคนส่วนใหญ่มักจะทำงานในแผนผังการทำงานของพวกเขามากกว่าที่เก็บของ แน่นอนถ้าคุณใช้ต้นไม้ทำงานเดี่ยวคุณอาจทำอะไรที่ 'พิเศษ' และอาจใช้มาโครเพื่อช่วย
CB Bailey

6

ใช้gitภายใน repo:

cd ./backup/git_repos/myfiles
git init --bare
git config core.worktree ../myfiles
git config core.bare false

จากนี้ไปคุณสามารถใช้gitภายใน./backup/git_repos/myfilesไดเรกทอรีโดยไม่ต้องตั้งค่าตัวแปรสภาพแวดล้อมหรือพารามิเตอร์เพิ่มเติม


ดูเหมือนว่าจะเป็นคำตอบที่ดีที่สุด แต่ฉันได้รับข้อความwarning: core.bare and core.worktree do not make senseนั่นหมายความว่ามันใช้งานไม่ได้?
hazrpg

1
ฉันยังคิดว่าเป็นงาน แต่มันบ่นเกี่ยวกับการเปลือยเมื่อตั้งค่า worktree นั่นเป็นเหตุผลที่ฉันจะตั้งค่าcore.bareในfalseภายหลัง
ถึง

อา! ที่เหมาะสมมากขึ้นในขณะนี้ ขอบคุณสำหรับสิ่งนั้น
hazrpg

1

คุณสามารถสร้างสคริปต์ "nodgit" (ไม่มีจุด GIT) ด้วยบางครั้งเช่น

#!/bin/sh
gits=/usr/local/gits
    x=`pwd`
    testdir() {( cd $1; pwd; )}
    while [ "$x" != "/" ]; do
      y=`echo $x|sed -e "s/\//__/g"`
      if ([ -d "$gits/$y" ]); then
        export GIT_DIR="$gits/$y"
        export GIT_WORK_TREE="$x"
        if ([ "$1" = "nodinit" ]); then
          mkdir -p "$GIT_DIR"
          git init --bare; exit $?
        elif ([ "$1" = "shell" ]); then
          bash; exit $?
        else
          exec git "$@"
        fi
      fi
      x=`testdir "$x/.."`
    done

คุณสามารถเรียก nodgit แทน git และมันจะตั้งค่าตัวแปรตามความจำเป็นโดยค้นหา repo git ตัวอย่างเช่นสมมติว่าคุณมี repo (เปลือย) ใน / usr / local / gits / __ home__foo_wibbles และคุณอยู่ใน / home / foo / wibbles / หนึ่งจากนั้นมันจะค้นหาไดเรกทอรีการทำงานที่ถูกต้อง (/ home / foo / wibbles) และ repo .

โอ้คุณสามารถใช้ "nodgit shell" เพื่อรับเชลล์ด้วยชุด vars ที่ถูกต้องเพื่อให้คุณสามารถใช้คำสั่ง git แบบเก่าได้


0

สมมติว่าmyfilesไดเรกทอรีของคุณมีอยู่แล้วและมีเนื้อหาบางส่วนคุณสามารถใช้ชีวิตกับสิ่งนี้ได้ไหม:

cd ~/backup
git init
git add myfiles

.gitไดเรกทอรีจะอยู่ในไม่ได้อยู่ในbackupmyfiles


แม้ว่ามันจะเรียงลำดับแก้ไขสิ่งที่ฉันต้องการฉันก็แค่เก็บโฟลเดอร์ myfiles ไว้ใต้ git แล้วก็ไม่มีอะไรอื่นอีกแล้ว
Rory

คุณสามารถเลือกไฟล์ที่คุณต้องการgitติดตามโดยใช้.gitignoreไฟล์ หากคุณต้องการเพิ่ม*และ!myfilesมันเพียงไดเรกทอรีที่จะถูกติดตาม แต่ถ้าคุณต้องการ repo แยกต่างหากสำหรับไดเรกทอรีอื่นคุณจะมีปัญหา ...
To1ne

0

ฉันสร้างสคริปต์ที่ดูเหมือน

~ / bin / คอมไพล์เฉือน:

#!/usr/bin/sh

export GIT_DIR=/home/Version-Control/cygwin-root.git/
export GIT_WORK_TREE=/

git --git-dir=$GIT_DIR --work-tree=$GIT_WORK_TREE "$@"

exit $?

มันซ้ำซ้อนที่จะใช้ --git_dir = $ GIT_DIR แต่เตือนฉันว่าฉันยังสามารถตั้งค่าตัวแปรสภาพแวดล้อมนอกสคริปต์

ตัวอย่างด้านบนใช้สำหรับติดตามการเปลี่ยนแปลงในระบบไฟล์ของ cygwin

สามารถสร้างหนึ่งสคริปต์ดังกล่าวสำหรับโครงการสำคัญใด ๆ ที่ต้องการสิ่งนี้ - แต่ / ไม่ / / มันคือการใช้งานหลักของฉัน

ด้านบนมีขนาดเล็กพอที่จะทำให้นามแฝงของเชลล์หรือฟังก์ชั่นถ้าคุณกำจัดความซ้ำซ้อน

ถ้าฉันทำสิ่งนี้บ่อยพอฉันจะรื้อฟื้นพื้นที่ทำงานเพื่อทำแผนที่ที่เก็บของ

"Boxes, Links, and Parallel Trees: Elements of a Configuration Management System", 
in Workshop Proceedings of the Software Management Conference. 1989.

ซึ่งมีคู่ที่ทันสมัยที่สุดใกล้เคียงคือการแมปเปอร์เพอร์หรือมุมมองสนับสนุนการชำระเงินบางส่วนเช่นเดียวกับที่ไม่ใช่ colocation ของพื้นที่ทำงานและ repo

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.