ベアgitリポジトリを通常のリポジトリ(インプレース)に変換するにはどうすればよいですか?


81

私は裸のgitリポジトリを持っていますが、sshを介してそのコンテンツにアクセスして参照する必要があります(ユーザーエクスペリエンスのようなファイルマネージャーで)。

私はそれを複製できると思います:

git clone -l <path_to_bare_repo> <new_normal_repo>

しかし、私のリポジトリのサイズは約20GBであり、それを複製するスペースがありません。ベアリポジトリをインプレースで変換して、作業コピーを作成する方法はありますか?


5
テストされていませんが、ベアリポジトリのコンテンツを.gitディレクトリに移動し、構成のbareパラメータをfalseに設定すると、git checkoutファイルを取得するだけの通常のリポジトリのように動作するはずです。
ヌーファルイブラヒム2012

あなたは、「その内容を閲覧」あなたはおそらく使用して裸のレポであなたが望むすべてを行うことができます何を意味するかに応じて、git showおよびgit cat-file
ウィリアムPursell

便利なヒントをありがとう。私は経験のようなもっとファイルマネージャーが必要です(質問を編集しました)。
nyi 2012年

ファイルシステムがハードリンクをサポートしていて、同じファイルシステムにクローンを作成する場合、clone -lはすべてのオブジェクトをハードリンクするため、これ以上ディスク領域を使用しません。ただし、他の人が指摘しているように、チェックアウト用のスペースが必要になります。
Neil Mayhew 2014

1
あなたの場合は、ベアリポジトリは、ディスクスペースの20ギガバイトを占め、どれだけ多くの作業ツリーの必要があるでしょうか?あなたがでください本当にそれだけのスペースがありますか?
ADTC 2015

回答:


113

:これは非常に単純な1コミットリポジトリでテストしました。これを再確認し、manページを読んでください。そして、StackOverflowで見つけたアドバイスに従う前に、バックアップしたことを常に確認してください。(あなたはバックアップしますよね?)

--bareリポジトリを非ベアに変換するには:

  1. 作る.gitリポジトリの最上位レベルのフォルダを。
  2. リポジトリ管理のもの(HEAD branches config description hooks info objects refsなど)を.git作成したばかりの場所に移動します。
  3. 実行git config --local --bool core.bare falseして、ローカルのgit-repositoryを非ベアに変換します。
  4. TamásPapによるコメントを介して)ステップ#3の後、ブランチmaster(またはメインブランチのいずれか)にいることがわかり、すべてのファイルが削除され、削除がステージングされます。それは正常です。手動でチェックアウトmasterするか、を実行するだけでgit reset --hard完了です。
  5. Royiによって報告された問題を解決するため)セクションの後に.git/configfetch = +refs/heads/*:refs/remotes/origin/*を追加するファイルを 編集します。それ以外の場合は、他のオリジンのブランチは表示されません。url = <...>[remote "origin"]git fetchorigin/master

これらの手順は、この質問の反対方向、「通常のリポジトリを裸のリポジトリにgit-convert」です。特に、上記の手順(どちらの方向でも)はを実行するのとは異なると述べているこの回答に注意してください。それがあなたに関係があるかどうかはわかりませんが、あなたは質問で言及しました。git-clonegit clone


2
私はすべて書きましたが、それでもファイルをプッシュしても表示されません。それは何でしょうか(私もdenyCurrentBranchを無視するように切り替えました)?
Royi 2016年

ありがとうございました!ある日仕事に取り掛かったところ、メインのリポジトリ(他の場所にいくつかのワークツリーがありました)が「裸」であると報告していることがわかりました。他のすべてのワークツリーは問題ありませんでした。どうやってくさびを解くのかわからなかったが、この答えを見つけて、それはうまくいった。
davidbak

17

私は少し異なるシナリオを持っていました:

解決:

  • そのコンテンツの.gitdirにベアリポジトリのクローンを作成します。
    git clone --bare https://github.com/user/project .git
  • ベアでないリポジトリとしてマークします。
    git config --local --bool core.bare false
  • インデックスをリセットします(そうでない場合、.git ベアリポジトリにはファイルが含まれていないため、すべてが削除されたと見なされます ' index'。)
    git reset HEAD -- .
    これにより、が復元され.git/indexます。

以前に取得したコンテンツを保持しながら、ベアリポジトリを非ベアリポジトリに効果的に変換しました。完全なスクリプト私が長年使ってきたが手順が含まれます。

cd /path/to/current/worktree

# That creates a .git directly at the right place
git clone --bare /url/of/repo .git

# restore the link between the local repo and its upstream remote repo
git config --local --bool core.bare false
git config --local remote.origin.fetch +refs/heads/*:refs/remotes/origin/*
git fetch origin
git branch -u origin/master master

# reset the index (not the working tree)
git reset HEAD -- .

しかし、私は受け入れられた解決策ADTCによって追加された有用なgit resetステップ使用)がより簡単であることを確認します。


また、行末が異なるマシンでベアリポジトリが作成された場合、これらの手順を実行した後でも、変更されたファイルが表示される場合があることにも注意してください。それは正常だと思います。gitは改行を修正しようとしています。理由はわかりません。
Juno Woods

つまり、基本的にGitHubリポジトリをベアとして複製し、非ベアに切り替え、「非リポジトリ」からすべてのファイルを手動で配置し、インデックスをリセットしましたか?そもそも、リポジトリを非ベアとしてクローンするのとどう違うのですか?非ベアクローンプロセスは、とにかくすべてのファイルをチェックアウトします。また、本当に必要な場合は、チェックアウトしたファイルを「非レポ」のファイルに置き換えることができます。
ADTC 2016

@ADTCの目標は、.git最初はアーカイブ(git以外)から作成された作業ツリー(リポジトリであることがわかっている)にサブフォルダーを作成することです。チェックアウトを行っていたフォルダーが空ではないため、ベア以外のリポジトリをチェックアウトできませんでした。git clone --no-checkoutサブフォルダーで非ベアを実行すると、.git1つ上のレベルに移動する必要があります。ベアクローンを作成することで、必要な.git場所にサブフォルダーを直接作成できました。:あなたはここで見ることができますスクリプトgithub.com/VonC/compileEverything/blob/...
VonC

「チェックアウトを行っていたフォルダーが空ではないため、ベア以外のリポジトリをチェックアウトできませんでした。」まだコミットされていない変更を含む非git作業ツリーがあり、それをGit対応の作業ツリーに変換した後にコミットするつもりですか?ええ、私は推測します、それはそのようなユースケースで機能します。個人的には、空のフォルダーにクローンを作成し、最初に2つを比較します(外部ツールを使用)。しかし、それは私だけです。
ADTC 2016年

@ADTCません:私はないではない「まだコミットされていない変更が含まれています非gitの作業ツリー」を持っています。私はないではない何かをコミットします。私持っているのは、レポの正確な作業ツリーです.git。不足しているのはそのすべてです。私は.gitベアクローンを通過し、その.gitフォルダーを非ベアクローンに変換git resetし、作業ツリーがすでに存在することをgitに認識させるために実行します。それはまさにgithub.com/VonC/compileEverything/blob/…が行うことです。
vonC 2016年

11

回答の情報を単純化して組み合わせるには:

ベアリポジトリが通常の.gitフォルダーと異なる点は3つあります。

  • core.bareは設定ファイルでtrueに設定されています
  • インデックスファイルと作業ツリーが存在しません
  • 「origin」リモートのデフォルトのrefspecは生成されません

したがって、ベアリポジトリを移動して新しいフォルダの.gitサブフォルダにすることができます。

mkdir clone
mv bare.git clone/.git

core.bareを変更します。

cd clone
git config --local --bool core.bare false

デフォルトのオリジンrefspecを追加して、通常と同じデフォルトを作成git fetchおよびgit push選択します。

git config remote.origin.fetch '+refs/heads/*:refs/remotes/origin/*'

そして、インデックスファイルと作業ツリーを生成します。

git checkout master

誤って間違った場所に入力された場合に備えて、ファイルを生成するのではgit checkoutなく、お勧めgit resetします。


10

元のポスターの質問は、物事を簡単な方法で行うのに十分なスペースがないことです。十分なスペースがある場合、答えははるかに簡単です。

git clone foo.git foo

これを避けたい理由は、リポジトリが大きくなると、gitcloneが停止することがあるためです。ベアリポジトリのrsyncを実行してから変換したいと思います。
SridharSarnobat19年

@SridharSarnobat、受け入れられた回答で説明されているタスクを実行することを検討してください:stackoverflow.com/a/10637882/377270-十分な空き容量がある人が簡単な方法で物事を行うことができるように、この1行の回答をここに置きます。
sarnold

6

ディスク容量が不足している場合は、通常のリポジトリに変換して作業ツリーを拡張することが問題になりますが、変換せずにベアリポジトリのコンテンツを参照できます。git cat-file -p <commit-sha>コミットで使用して、それが参照するツリーを確認します。git cat-file -p <blob-sha>ブロブによって参照されるファイルの内容を確認するために使用します。git show <sha>:pathパスでblobの内容を確認するには、shaがコミットまたはツリーのいずれかである場合に使用します。


1
あなたは正しいですが、私はそれをもっと便利に閲覧する必要があります(ssh上のファイルマネージャーで)。したがって、ディスク容量の増加に対応する必要があります。
nyi 2012年

1
実際、これは本当の問題です(+1)。作業ツリーは、多くの場合、ディスク領域の半分を消費します。gitの履歴が積極的に圧縮されていることも一因です。
jpaugh 2017

4

cd 裸のレポに入れて

  1. どちらか:
git config core.bare false
git reset --hard
  1. または
git clone X.git X

(Xという名前の通常のgitリポジトリを提供します)


これは最も簡単な解決策であり、2019年にそれが機能することを確認できます(最初のアプローチ)。
SridharSarnobat19年

私が忘れていたちょっとしたメモ(すべての回答に適用):最初にプッシュしてリモートURLを設定するときに、構成ファイルを編集する必要があります。
SridharSarnobat19年

2

別のワークツリーで作業してもかまわない場合は、

git worktree add ../repo2
cd ..
git status # now works fine

これはクローンではないことに注意してください。


これは素晴らしいことですが、なぜこれがリストの上位にないのか
わかり

0

プッシュツーデプロイ

ベアリモートを標準リポジトリに変換するのではなく、hooksディレクトリのpost-receiveスクリプトを使用して、リポジトリをデプロイメントディレクトリに展開できます。

これは、Push-to-Deployを設定する良い例です。

参照しやすいように、これは上記のリンクのスクリプトコンテンツの例です。「master」ブランチから、リポジトリの親ディレクトリと同じレベルにある「deploy」という名前のディレクトリにプッシュのみをデプロイします。

#!/usr/bin/env ruby
# post-receive

# 1. Read STDIN (Format: "from_commit to_commit branch_name")
from, to, branch = ARGF.read.split " "

# 2. Only deploy if master branch was pushed
if (branch =~ /master$/) == nil
    puts "Received branch #{branch}, not deploying."
    exit
end

# 3. Copy files to deploy directory
deploy_to_dir = File.expand_path('../deploy')
`GIT_WORK_TREE="#{deploy_to_dir}" git checkout -f master`
puts "DEPLOY: master(#{to}) copied to '#{deploy_to_dir}'"
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.