追跡したいファイルの外側に.gitフォルダーを保存できますか?


147

バックアップシステムとしてgitを使用するという変わった考えがあります。たとえば、。/ backup / myfilesというディレクトリがあり、gitを使用してそれをバックアップしたいとします。物事をきれいに保つために、myfilesフォルダーに.gitディレクトリーを置きたくないので、。/ backup / git_repos / myfilesを作成できると思いました。git docsを見て、これを試してみました:

$ 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フォルダーを別の場所に保持しながら、「ドットファイル」(.bashrc、.vimrcなど)をホームディレクトリに保持することもできます。
フィリップ

6
最も率直な答え:stackoverflow.com/a/19548676/170352(古い賛成投票のために埋められました)
Brandon Bertelsen

1
書き込みアクセス権がない場合、または作業ディレクトリに変更を加えたくない場合(.git /の追加など)は、以下のLeoによるこの回答(古い賛成投票によって埋められたもの)が最適です。
神戸ジョン2016年

1
@Philip(dotfilesリポジトリにGitサブモジュールも含まれている場合を除く)。Gitは、外部ワークツリーと組み合わせたサブモジュールをサポートしていません。
maxschlepzig 2016

回答:


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

これはあなたが望むことをしますが、あなたがこれまでに使ったすべてのgitコマンドでそれを指定しなければならないときは明らかに吸います。

エクスポートするGIT_WORK_TREE=.GIT_DIR=../backup、Gitは各コマンドでそれらを取得します。ただし、シェルごとに1つのリポジトリで作業することはできます。

.gitディレクトリを他の場所にシンボリックリンクするか、メインのバックアップディレクトリから.gitディレクトリへのシンボリックリンクを作成することをお勧めします。


1
すべてのコマンドでgit-dirとwork-treeを指定せず、シンボリックリンクなしで同じものをアーカイブできます。私の答えを見てください。
niks 2012

シンボリックリンクの欠点は、それが作業ツリー内に存在することです。他のプロセスが作業ツリーを一掃すると、シンボリックリンクが失われます
Jeff

さらに、OPが自分の作業ツリーに.gitサブディレクトリを必要としていない場合、なぜシンボリックリンクが必要なのでしょうか。
ジェフ

@ジェフ:トレードオフのため。(彼のバックアップケースでは、彼の作業ツリーを一掃することは、おそらく他のディレクトリ(レポ自体など)を一掃することよりも大きな問題ではありません。)
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バージョン管理を設定できます。--git-dirすべてのgitコマンドで使用するか、リポジトリ内から(作業ディレクトリではなく)すべてのコマンドを実行する場合は、.gitファイルを省略できるため、作業ディレクトリ内にファイルを作成する必要はありません。レオの回答も参照


7
既存のリポジトリにもこれを行うことができます:.gitフォルダーを好きな場所に移動し、.gitファイルを追加してそれを指すようにすると、通常どおりにリポジトリの使用を
続行

gitコマンドはリポのルートからしか発行できないことに注意してください。サブフォルダに入ると混乱します!(これは、gitdirに指定された値が相対または絶対であるかどうかに関係なく発生します。)
joachim 2012

2
この問題を修正するには、実際のgit構成ファイルで「core.worktree」を指定します。つまり、.gitでポイントするフォルダー内のファイルです。
joachim

2
はい、それは私が私の答えの2番目の文で説明したものです。core.worktreeもちろん、構成値は.gitフォルダーの構成ファイルに格納されています。
niks 2012

1
これらの指示を使用すると、作成されたリポジトリがベアリポジトリになり、エラーが発生しますfatal: core.worktree and core.bare do not make sense。設定を変更するだけのようですので、それを解決する必要はありません。
Steven Lu

62

(および)の--separate-git-dirオプションを使用して、私のバージョンのgit()でこれを実現できます。このオプションはgitリポジトリを作業ツリーから分離し、作業ツリーのルートにファイルシステムに依存しないgitシンボリックリンク(という名前のファイルの形式)を作成します。結果はniksの答えと同じだと思いますgit initgit clone1.7.11.3.git

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 2016

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
        ...

このアプローチには2つの利点があります。

  • コマンドラインオプションや.gitファイルを用意する必要がなくなります。リポジトリのルート内から通常どおりに操作できます。
  • それを所有していない場合でも、ファイルシステムをバージョン管理することができます。Gitはリポジトリの場所にのみ書き込みます。

私が遭遇した唯一の警告は、.gitignoreファイルを使用する代わりに編集することですinfo/exclude

read_only_repos/foo元のファイルがバージョン管理されていなくても、自分のリポジトリでリモートとしてリポジトリを使用できます。


まあ、これはまったく同じコマンドです。私が見る唯一の違いは、あなたが--work-treeと--git-dir引数の順序を交換したことです。もちろん、.gitファイルへの書き込みアクセス権がないため、作業ディレクトリに.gitファイルを作成しません。それでも、書き込みアクセス権のないディレクトリにバージョン管理を使用するのは、良い使用例です。:-)
niks 2016

3
了解しました。重要なのは、作業ディレクトリの外にリポジトリを作成することです。
レオ

4
私はこれが好きです-他の参加者がgitが使用されていることを知らなくても、Dropboxと共有しているディレクトリでgitを使用できます。
クエンティンスタッフォードフレイザー

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)"

これを実行すると、addコマンドは期待どおりに機能するはずです。

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

実際の作業ツリーではなく、最初に../git_repos/myfiles.gitにcdすると、 'git add foo'が機能し、-git-dir allを指定する必要がないことがわかりました時間。
スティーブフォリー

1
それは事実ですが、ほとんどの人はリポジトリよりも作業ツリーで作業する傾向があると思います。もちろん、分離された作業ツリーを使用している場合は、おそらく「特別な」ことを行っており、役立つマクロを使用している可能性があります。
CBベイリー、

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.barefalseます。
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リポジトリを探して必要に応じて変数を設定します。たとえば、/ 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の下に保存し、それ以外は何もしません。
ロリー・

ファイルをgit使用して追跡するファイルの選択を保持でき.gitignoreます。追加*!myfilesた場合、そのディレクトリのみが追跡されます。しかし、別のディレクトリ用に別のリポジトリが必要な場合は、問題が発生します...
To1ne

0

次のようなスクリプトを作成します

〜/ bin / git-slash:

#!/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システムファイルに対するローカルの変更を追跡するためのものです。

これを必要とするすべての主要なプロジェクトでそのようなスクリプトを1つ作成できますが、/を使わない/が私の主な用途です。

上記は、冗長性を排除した場合、シェルのエイリアスまたは関数を作成するのに十分な大きさです。

これを頻繁に行うと、ワークスペースからリポジトリへのマッピングが復活します。

"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.