추적하려는 파일 외부에 .git 폴더를 저장할 수 있습니까?


147

git을 백업 시스템으로 사용하는 것이 이상합니다. ./backup/myfiles 디렉토리가 있고 git을 사용하여 백업하고 싶다고 가정 해 봅시다. 일을 깨끗하게 유지하기 위해 myfiles 폴더에 .git 디렉토리를 갖고 싶지 않으므로 ./backup/git_repos/myfiles를 만들 수 있다고 생각했습니다. 자식 문서를 살펴보면서 이것을 시도했습니다.

$ 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
백업 아이디어뿐만 아니라 .git 폴더를 다른 곳에 유지하면서 "dotfiles"(. bashrc, .vimrc 등)를 홈 디렉토리에 유지하는 데 사용할 수도 있습니다.
Philip

6
가장 답답한 답변 : stackoverflow.com/a/19548676/170352 (오래된 투표로 인해 매장 됨)
Brandon Bertelsen 2016 년

1
쓰기 액세스 권한이 없거나 작업 디렉토리를 변경하지 않으려는 경우 (예 : .git / 등 추가) Leo (이전 upvotes에 의해 묻혀 있음)의 아래 답변 가장 좋습니다.
KobeJohn

1
닷 파일 저장소에 Git 서브 모듈이 없다면 @Philip. Git은 외부 작업 트리와 함께 하위 모듈을 지원하지 않습니다.
maxschlepzig 2016 년

답변:


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

이것은 당신이 원하는 것을 할 것이지만 당신이 사용하는 모든 git 명령으로 그것을 지정해야 할 때 분명히 빨라질 것입니다.

당신은 내보낼 수 GIT_WORK_TREE=.GIT_DIR=../backup및 망할 놈의 각 명령에 그들을 데리러 것입니다. 그래도 쉘 당 하나의 저장소에서 편안하게 작업 할 수 있습니다.

차라리 .git 디렉토리를 다른 곳으로 심볼릭 링크하거나 기본 백업 디렉토리에서 .git 디렉토리로 심볼릭 링크를 만드는 것이 좋습니다.


1
모든 명령에서 git-dir 및 작업 트리를 지정하지 않고 심볼릭 링크를 사용하지 않고 동일한 아카이브를 수행 할 수 있습니다. 내 대답을 참조하십시오.
niks

심볼릭 링크의 단점은 작업 트리 내에 존재한다는 것입니다. 다른 프로세스가 작업 트리
Jeff

또한 OP가 작업 트리에서 .git 하위 디렉토리를 원하지 않으면 왜 심볼릭 링크를 원합니까?
Jeff

@Jeff : 트레이드 오프. (백업의 경우, 작업 트리를 지우는 것이 다른 디렉토리 (레포 자체와 같은)를 지우는 것보다 더 큰 관심사가 아닐 것입니다.)
Sz.

1
나는 이것을 내 노트에 direnv 와 함께 사용 하고 있습니다. 내 작업 트리는 Dropbox의 폴더에 있고 git 폴더는 외부에 있습니다. 이렇게하면 모든 컴퓨터에서 쉽게 변경 사항을 적용 할 수 있지만 변경된 내용을 확인하고 중요한 사항이 변경된 경우에만 커밋 할 수 있습니다. 감사합니다
Paulo 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

현재 디렉토리는 작업 트리가되고 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-dir모든 자식 명령 또는 (대신 작업 디렉토리의) 저장소 내에서 모든 명령을 실행, 당신은 .git 파일을 남길 수 있으므로 작업 디렉토리 내의 모든 파일을 만들 필요가 없습니다. 레오 답변 참조


7
이 작업을 기존 리포지토리로도 수행 할 수 있습니다. .git 폴더를 원하는 곳으로 옮기고 .git 파일을 추가하여 가리 키십시오. 그러면 평소와 같이 리포지토리를 계속 사용할 수 있습니다.
joachim

리포지토리의 루트에서만 git 명령을 실행할 수 있습니다. 하위 폴더로 들어가면 혼동됩니다! (이것은 gitdir 대한 주어진 값이 상대적 또는 절대적인지 여부 일어난다.)

2
이에 대한 수정은 실제 git 구성 파일에 'core.worktree'를 지정하는 것입니다. 즉, .git에서 가리키는 폴더의 파일입니다.
joachim

2
그렇습니다. 이것이 두 번째 문장에서 설명한 것입니다. 구성 값 core.worktree은 물론 .git 폴더의 구성 파일에 저장되며 여기서 .git 파일은 가리 킵니다.
niks

1
내가이 지시 사항을 사용할 때 repo가 ​​만들어지는 저장소가되고 오류가 발생하는 것을 발견했다 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 기호 링크 (라는 파일 형식 )를 작성합니다. 결과는 niks의 대답 과 동일하다고 생각합니다 .

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

2
+1 명령 행 옵션을 사용하는 것이 init더 명확하고 깨끗해 보입니다
goncalopp

Windows에서 repo.git은닉 속성 세트로 작성됩니다. 그런 다음 수동으로 변경합니다. 이것이 안전한지 알고 있습니까?
PA.

+1 예 git은 버전 1.7.5에서이 명령 행 옵션을 배웠는데, 당시에는 사용할 수 없었습니다. 이 매개 변수를 사용하도록 제안하기 위해 답변을 업데이트했습니다.
niks

25

나는 niks의 대답에 사용 된 --work-tree--git-dir디렉토리 를 뒤집는 것이 더 간단하다는 것을 알았습니다.

$ 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은 저장소 위치에만 쓸 것입니다.

내가 만난 유일한 경고는 .gitignore파일 을 사용하는 대신 편집하는 것 info/exclude입니다.

그런 다음 read_only_repos/foo원래 파일의 버전이 제어되지 않더라도 저장소를 원격 저장소 로 원격으로 사용할 수 있습니다 .


이것은 정확히 같은 명령입니다. 내가 볼 수있는 유일한 차이점은 --work-tree 및 --git-dir 인수의 순서를 바꿨다는 것입니다. 그리고 물론 쓰기 권한이 없으므로 작업 디렉토리에 .git 파일을 작성하지 마십시오. 그럼에도 불구하고, 디렉토리에 대한 쓰기 액세스 권한이없는 디렉토리에 대한 버전 제어를 사용하는 것이 좋습니다. :-)
niks

3
맞아요. 핵심은 작업 디렉토리 외부에 저장소를 작성하는 것입니다.
Leo

4
나는 이것을 좋아합니다-다른 참가자가 git이 사용 중임을 알지 않고도 Dropbox와 공유하는 디렉토리에서 git을 사용할 수 있습니다.
Quentin Stafford-Fraser

19

베어 트리 저장소와 같이 '.git'확장자를 가진 특이한 위치에 작업 트리가있는 git 저장소 인 디렉토리의 이름을 지정하는 것이 일반적입니다.

mkdir ../git_repos/myfiles.git

--work-tree초기에 옵션을 제공했다면 core.worktreegit 변수를 자동으로 설정합니다. 즉, git 디렉토리를 지정하면 git이 작업 트리를 찾을 위치를 알 수 있습니다.

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

그러나 사실 후에도이 변수를 설정할 수 있습니다.

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

이 작업을 완료하면 add 명령이 예상대로 작동합니다.

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

실제 작업 트리에 있지 않고 먼저 ../git_repos/myfiles.git으로 cd하면 'git add foo'가 작동하므로 --git-dir all을 지정할 필요가 없습니다. 시간.
Steve Folly

1
사실이지만 대부분의 사람들은 리포지토리가 아닌 작업 트리에서 작업하는 경향이 있다고 생각합니다. 물론 분리 된 작업 트리를 사용하는 경우 아마도 '특별한'일을하고 있으며 매크로를 사용하여 도움이 될 수 있습니다.
CB Bailey

6

git저장소 내부에서 사용하십시오 .

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
나는 여전히 작품이라고 생각하지만 작업 트리를 설정할 때 맨손으로 불평합니다. 그래서 내가 나중에 설정 core.bare하는 이유 false입니다.
To1ne

아! 이제 더 의미가 있습니다. 고마워
hazrpg

1

"nodgit"스크립트 (No Dot 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

git 대신 nodgit을 호출 할 수 있으며 git repo를 찾아 변수를 설정합니다. 예를 들어 / usr / local / gits / __ home__foo_wibbles에 (맨손) 저장소가 있고 / home / foo / wibbles / one에 있으면 올바른 작업 디렉토리 (/ home / foo / wibbles)와 저장소를 찾습니다. .

또한 "nodgit shell"을 사용하여 올바른 vars 세트가있는 쉘을 얻을 수 있으므로 일반 git 명령을 사용할 수 있습니다.


0

myfiles디렉토리가 이미 존재하고 내용이 있다고 가정하면 다음 과 같이 살 수 있습니까?

cd ~/backup
git init
git add myfiles

.git디렉토리에있을 것입니다 backup하지에 myfiles.


그것은 내가 원하는 것을 고칠 것이지만, 오히려 myfiles 폴더를 git 아래에 저장하고 싶습니다.
Rory

파일을 git사용하여 추적 하려는 파일을 계속 선택할 수 있습니다 .gitignore. 당신은 추가하려는 경우 *!myfiles그것에, 해당 디렉토리가 추적됩니다. 그러나 다른 디렉토리에 대해 별도의 저장소를 원한다면 문제가 생길 것입니다.
To1ne

0

다음과 같은 스크립트를 만듭니다

~ / bin / git- 슬래시 :

#!/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 시스템 파일의 로컬 변경 사항을 추적하기위한 것입니다.

이것을 필요로하는 주요 프로젝트에 대해 하나의 스크립트를 만들 수는 있지만 /.git없이 /가 내 주요 용도입니다.

이중화를 제거하면 위의 내용은 쉘 별명 또는 기능을 작성하기에 충분히 작습니다.

이 작업을 충분히 자주 수행하면 작업 공간 대 저장소 매핑이 다시 활성화됩니다.

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

가장 현대적인 대응은 Perforce 매핑 또는 뷰 이며, 부분 체크 아웃과 비 작업 공간 및 리포지토리를 지원합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.