私は.git
リポジトリディレクトリなしでツリーのコピーを作成する良い「git export」ソリューションがあるかどうか疑問に思いました。私が知っている方法は少なくとも3つあります。
git clone
に続いて.git
リポジトリディレクトリを削除します。git checkout-index
はこの機能をほのめかしていますが、「目的のツリーをインデックスに読み込むだけです」から始めています。git-export
は、基本的に一時的な場所にgit clone
を入力し、最後の宛先にrsync --exclude='.git'
を入力するサードパーティスクリプトです。これらの解決策のどれも本当に満足のいくものとして私を襲った。どちらもターゲットディレクトリを最初に空にする必要があるため、svn export
に最も近いものはオプション1です。しかし、ツリーをインデックスに読み込むことが何を意味するのかを理解できるのであれば、選択肢2はさらに優れているようです。
おそらくこれを達成するための最も簡単な方法は git archive
を使うことです。もしあなたが本当に展開されたツリーだけが本当に必要なら、あなたはこのようなことをすることができます。
git archive master | tar -x -C /somewhere/else
ほとんどの場合、gitから何かを「エクスポート」する必要があるのですが、いずれにせよ圧縮アーカイブが欲しいので、このようにします。
git archive master | bzip2 >source-tree.tar.bz2
Zipアーカイブ:
git archive --format Zip --output /full/path/to/zipfile.Zip master
git help archive
詳細については、非常に柔軟です。
アーカイブに.gitディレクトリが含まれていなくても、.gitignore、.gitattributesなどの他の隠されたgit固有のファイルが含まれていることに注意してください。アーカイブを実行する前に、.gitattributesファイルでexport-ignore属性を使用し、これをコミットしてください。 続きを読む...
注:索引のエクスポートに関心がある場合は、コマンドは
git checkout-index -a -f --prefix=/destination/path/
(詳しくは Gregの答え をご覧ください)
私は選択肢2が何を意味するのかを見つけました。リポジトリから、次のことができます。
git checkout-index -a -f --prefix=/destination/path/
パスの末尾のスラッシュは重要です。そうしないと、ファイルの先頭に/ pathという接頭辞が付いたファイルになります。
通常の状況ではインデックスにリポジトリの内容が含まれているので、「目的のツリーをインデックスに読み込む」ための特別な操作はありません。それはもうそこにあります。
インデックス内のすべてのファイルをチェックアウトするには-a
フラグが必要です(この状況でこのフラグを省略することがどういう意味なのかはよくわかりません)。 -f
フラグは、出力内の既存のファイルを強制的に上書きします。通常、このコマンドでは実行されません。
これは私が探していた一種の "git export"のようです。
git archive
はリモートリポジトリでも動作します。
git archive --format=tar \
--remote=ssh://remote_server/remote_repository master | tar -xf -
リポジトリ内の特定のパスをエクスポートするには、gitの最後の引数として必要なだけのパスを追加します。
git archive --format=tar \
--remote=ssh://remote_server/remote_repository master path1/ path2/ | tar -xv
svn export
を使うだけです。
私の知る限りではGithubはarchive --remote
を許可していません。 GitHubは svnと互換性があります そしてそれらはすべてのgitレポジトリsvn
にアクセス可能であるので、あなたはあなたのGitHub URLへのいくつかの調整で普通にするようにsvn export
を使うことができます。
たとえばリポジトリ全体をエクスポートするには、URL内のtrunk
がmaster
に置き換えられることに注意してください(または プロジェクトのHEADブランチが に設定されているものはすべて)。
svn export https://github.com/username/repo-name/trunk/
そして、単一のファイル、あるいは特定のパスやフォルダをエクスポートすることもできます。
svn export https://github.com/username/repo-name/trunk/src/lib/folder
HEAD
ブランチまたは master ブランチは、trunk
を使用して利用できます。
svn ls https://github.com/jquery/jquery/trunk
非HEAD
branches は/branches/
の下でアクセス可能です。
svn ls https://github.com/jquery/jquery/branches/2.1-stable
同じ方法で/tags/
の下のすべての tags
svn ls https://github.com/jquery/jquery/tags/2.1.3
"ツリー全体をエクスポート"するためのgit-checkout-indexの使用
プレフィックス機能は基本的に "ツリーとしてエクスポート"機能としてgit-checkout-indexを使うのを簡単にします。目的のツリーをインデックスに読み込んで、次のようにします。
$ git checkout-index --prefix=git-export-dir/ -a
私はgit-checkout-index
の周りにあなたがこのように使うことができる簡単なラッパーを書きました:
git export ~/the/destination/dir
インストール先ディレクトリが既に存在する場合は、-f
または--force
を追加する必要があります。
インストールは簡単です。スクリプトをPATH
のどこかにドロップして、実行可能であることを確認してください。
これはSVNよりもGitの問題ではないようです。 SVNはすべてのサブディレクトリに.svnフォルダを置くのに対し、Gitはリポジトリルートに.gitフォルダを置くだけです。そのため "svn export"は再帰的なコマンドラインマジックを避けますが、Gitでは再帰は必要ありません。
と同等
svn export . otherpath
既存のリポジトリ内に
git archive branchname | (cd otherpath; tar x)
と同等
svn export url otherpath
です
git archive --remote=url branchname | (cd otherpath; tar x)
.gitattributes
export-ignore
のファイルを除外しない場合は、git checkout
を試してください
mkdir /path/to/checkout/
git --git-dir=/path/to/repo/.git --work-tree=/path/to/checkout/ checkout -f -q
-f
インデックスからパスをチェックアウトするとき、結合されていないエントリで失敗しないでください。代わりに、マージされていないエントリは無視されます。
そして
-q
詳細表示を避ける
さらに、任意のブランチまたはタグを取得するか、SHA1を追加するだけでSVNのような特定のコミットリビジョンから取得できます(GitのSHA1はSVNのリビジョン番号と同等です)
mkdir /path/to/checkout/
git --git-dir=/path/to/repo/.git --work-tree=/path/to/checkout/ checkout 2ef2e1f2de5f3d4f5e87df7d8 -f -q -- ./
/path/to/checkout/
は空である必要があります。Gitはファイルを削除しませんが、警告なしで同じ名前のファイルを上書きします
更新:タグ、ブランチ、またはSHA1を使用したエクスポートのチェックアウトを使用するときに、斬首の問題を回避したり、作業リポジトリをそのまま残したりするには、最後に-- ./
を追加する必要があります
二重ダッシュ--
は、ダッシュの後のすべてがパスまたはファイルであることをgitに伝えます。また、この場合、git checkout
にHEAD
を変更しないように伝えます
例:
このコマンドは、libsディレクトリだけでなく、その正確なコミットからreadme.txt
ファイルも取得します
git --git-dir=/path/to/repo/.git --work-tree=/path/to/checkout/ checkout fef2e1f2de5f3d4f5e87df7d8 -f -q -- ./libs ./docs/readme.txt
これにより、my_file_2_behind_HEAD.txt
ヘッドの後ろの2つのコミットHEAD^2
が作成(上書き)されます。
git --git-dir=/path/to/repo/.git --work-tree=/path/to/checkout/ checkout HEAD^2 -f -q -- ./my_file_2_behind_HEAD.txt
別のブランチのエクスポートを取得するには
git --git-dir=/path/to/repo/.git --work-tree=/path/to/checkout/ checkout myotherbranch -f -q -- ./
./
は、リポジトリのルートに関連していることに注意してください。
私はgitサブモジュールを広く使っています。これは私のために働く:
rsync -a ./FROM/ ./TO --exclude='.*'
Gitリポジトリをエクスポートする方法を探しているとき、私はこのページを頻繁に見ました。この質問に対する私の答えは、svn exportがgitと比較して意図的に持っている3つの特性を考慮しています、なぜならsvnは集中化されたリポジトリアプローチに従うからです。
Svnを使って特定のブランチをエクスポートするには、適切なパスを指定します。
git clone --depth 1 --branch master git://git.somewhere destination_path
rm -rf destination_path/.git
特定のリリースをビルドするとき、例えば--branch stable
や--branch release/0.9
のように安定版ブランチを複製するのが便利です。
これにより、.dotファイルを除くすべてのコンテンツがコピーされます。私はこれを使用して、gitクローンプロジェクトを.gitファイルを使わずに私のWebアプリケーションのgitリポジトリにエクスポートします。
cp -R ./path-to-git-repo/path/to/destination /
平凡な古いbashはちょうど素晴らしいです:)
Cloneと同じくらい簡単に、.gitフォルダを削除します。
git clone url_of_your_repo path_to_export && rm -rf path_to_export/.git
はい、 this はgitをアーカイブに含めずにコードをアーカイブするためのクリーンできちんとしたコマンドで、gitのコミット履歴を気にせずにやり取りするのに適しています。
git archive --format Zip --output /full/path/to/zipfile.Zip master
私はちょうどあなたがそうである場合にそれを指摘したいと思います
そうすれば、言及したcp foo [destination]
の代わりにgit-archive master foo | -x -C [destination]
を使うことができます。
GitHubユーザーの場合、git archive --remote
メソッドは直接動作しません。 エクスポートURLは一時的なものです 。 GitHubにURLを尋ねてから、そのURLをダウンロードする必要があります。 curl
はそれを簡単にします:
curl -L https://api.github.com/repos/VENDOR/PROJECT/tarball | tar xzf -
これにより、エクスポートされたコードがローカルディレクトリに格納されます。例:
$ curl -L https://api.github.com/repos/jpic/bashworks/tarball | tar xzf -
$ ls jpic-bashworks-34f4441/
break conf docs hack LICENSE mlog module mpd mtests os README.rst remote todo vcs vps wepcrack
編集
(githubからのランダムなディレクトリではなく)特定のexistingディレクトリにコードを置きたい場合は、
curl -L https://api.github.com/repos/VENDOR/PROJECT/tarball | \
tar xzC /path/you/want --strip 1
あなたはZipファイルとして任意のコミットでリモートリポジトリをアーカイブすることができます。
git archive --format=Zip --output=archive.Zip --remote=USERNAME@HOSTNAME:PROJECTNAME.git HASHOFGITCOMMIT
あなたがサブモジュールで動作する何かが欲しいなら、これは行く価値があるかもしれません。
注意:
仮定:
cd MASTER_DIR && tar -zcvf ../DEST_DIR/export.tar.gz --exclude = '。git *'。 && cd ../DEST_DIR/ && tar xvfz export.tar.gz && rm export.tar.gz
Git-exportのbash実装.
空のファイルの作成と削除のプロセスを 'git-archive'の実装で再利用することを目的として、独自の機能に分割しました(詳細は後述).
ターゲットのエクスポートフォルダから不要なファイルを削除するために、プロセスに「.gitattributes」ファイルも追加しました。 'git-export'機能をより効率的にしながら、プロセスに冗長性を含めました。
EMPTY_FILE = "。empty";
function create_empty () {
## Processing path (target-dir):
TRG_PATH="${1}";
## Component(s):
EXCLUDE_DIR=".git";
echo -en "\nAdding '${EMPTY_FILE}' files to empty folder(s): ...";
find ${TRG_PATH} -not -path "*/${EXCLUDE_DIR}/*" -type d -empty -exec touch {}/${EMPTY_FILE} \;
#echo "done.";
## Purging SRC/TRG_DIRs variable(s):
unset TRG_PATH EMPTY_FILE EXCLUDE_DIR;
return 0;
}
declare -a GIT_EXCLUDE;
function load_exclude () {
SRC_PATH="${1}";
ITEMS=0; while read LINE; do
# echo -e "Line [${ITEMS}]: '${LINE%%\ *}'";
GIT_EXCLUDE[((ITEMS++))]=${LINE%%\ *};
done < ${SRC_PATH}/.gitattributes;
GIT_EXCLUDE[${ITEMS}]="${EMPTY_FILE}";
## Purging variable(s):
unset SRC_PATH ITEMS;
return 0;
}
function purge_empty () {
## Processing path (Source/Target-dir):
SRC_PATH="${1}";
TRG_PATH="${2}";
echo -e "\nPurging Git-Specific component(s): ... ";
find ${SRC_PATH} -type f -name ${EMPTY_FILE} -exec /bin/rm '{}' \;
for xRULE in ${GIT_EXCLUDE[@]}; do
echo -en " '${TRG_PATH}/{${xRULE}}' files ... ";
find ${TRG_PATH} -type f -name "${xRULE}" -exec /bin/rm -rf '{}' \;
echo "done.'";
done;
echo -e "done.\n"
## Purging SRC/TRG_PATHs variable(s):
unset SRC_PATH; unset TRG_PATH;
return 0;
}
function git-export () {
TRG_DIR="${1}"; SRC_DIR="${2}";
if [ -z "${SRC_DIR}" ]; then SRC_DIR="${PWD}"; fi
load_exclude "${SRC_DIR}";
## Dynamically added '.empty' files to the Git-Structure:
create_empty "${SRC_DIR}";
GIT_COMMIT="Including '${EMPTY_FILE}' files into Git-Index container."; #echo -e "\n${GIT_COMMIT}";
git add .; git commit --quiet --all --verbose --message "${GIT_COMMIT}";
if [ "${?}" -eq 0 ]; then echo " done."; fi
/bin/rm -rf ${TRG_DIR} && mkdir -p "${TRG_DIR}";
echo -en "\nChecking-Out Index component(s): ... ";
git checkout-index --prefix=${TRG_DIR}/ -q -f -a
## Reset: --mixed = reset HEAD and index:
if [ "${?}" -eq 0 ]; then
echo "done."; echo -en "Resetting HEAD and Index: ... ";
git reset --soft HEAD^;
if [ "${?}" -eq 0 ]; then
echo "done.";
## Purging Git-specific components and '.empty' files from Target-Dir:
purge_empty "${SRC_DIR}" "${TRG_DIR}"
else echo "failed.";
fi
## Archiving exported-content:
echo -en "Archiving Checked-Out component(s): ... ";
if [ -f "${TRG_DIR}.tgz" ]; then /bin/rm ${TRG_DIR}.tgz; fi
cd ${TRG_DIR} && tar -czf ${TRG_DIR}.tgz ./; cd ${SRC_DIR}
echo "done.";
## Listing *.tgz file attributes:
## Warning: Un-TAR this file to a specific directory:
ls -al ${TRG_DIR}.tgz
else echo "failed.";
fi
## Purgin all references to Un-Staged File(s):
git reset HEAD;
## Purging SRC/TRG_DIRs variable(s):
unset SRC_DIR; unset TRG_DIR;
echo "";
return 0;
}
出力:
$ git-export /tmp/rel-1.0.0
空のフォルダに「空の」ファイルを追加します。
インデックスコンポーネントのチェックアウト:...完了。
HEADとインデックスをリセットしています... ...完了。
Git固有のコンポーネントを削除しています:...
'/tmp/rel-1.0.0/{.buildpath}'ファイル...完了。
'/tmp/rel-1.0.0/{.project}'ファイル...完了。
'/tmp/rel-1.0.0/{.gitignore}'ファイル...完了。
'/tmp/rel-1.0.0/{.git}'ファイル...完了。
'/tmp/rel-1.0.0/{.gitattributes}'ファイル...完了。
'/tmp/rel-1.0.0/{*.mno}'ファイル...完了。
'/tmp/rel-1.0.0/{*~}'ファイル...完了。
'/tmp/rel-1.0.0/{.*~}'ファイル...完了。
'/tmp/rel-1.0.0/{*.swp}'ファイル...完了。
'/tmp/rel-1.0.0/{*.swo}'ファイル...完了。
'/tmp/rel-1.0.0/{.DS_Store}'ファイル...完了。
'/tmp/rel-1.0.0/{.settings}'ファイル...完了。
'/tmp/rel-1.0.0/{.empty}'ファイル...完了。
行った。
チェックアウト済みコンポーネントのアーカイブ:...完了。
-rw-r - r-- 1 admin wheel 25445901 3 Nov 12:57 /tmp/rel-1.0.0.tgz
私は今 'git archive'機能を 'create_empty'機能と他の機能を利用する単一のプロセスに組み込んでいます。
function git-archive () {
PREFIX="${1}"; ## Sudo mkdir -p ${PREFIX}
REPO_PATH="`echo "${2}"|awk -F: '{print $1}'`";
RELEASE="`echo "${2}"|awk -F: '{print $2}'`";
USER_PATH="${PWD}";
echo "$PREFIX $REPO_PATH $RELEASE $USER_PATH";
## Dynamically added '.empty' files to the Git-Structure:
cd "${REPO_PATH}"; populate_empty .; echo -en "\n";
# git archive --prefix=git-1.4.0/ -o git-1.4.0.tar.gz v1.4.0
# e.g.: git-archive /var/www/htdocs /repos/domain.name/website:rel-1.0.0 --explode
OUTPUT_FILE="${USER_PATH}/${RELEASE}.tar.gz";
git archive --verbose --prefix=${PREFIX}/ -o ${OUTPUT_FILE} ${RELEASE}
cd "${USER_PATH}";
if [[ "${3}" =~ [--explode] ]]; then
if [ -d "./${RELEASE}" ]; then /bin/rm -rf "./${RELEASE}"; fi
mkdir -p ./${RELEASE}; tar -xzf "${OUTPUT_FILE}" -C ./${RELEASE}
fi
## Purging SRC/TRG_DIRs variable(s):
unset PREFIX REPO_PATH RELEASE USER_PATH OUTPUT_FILE;
return 0;
}
私の好みは実際にあなたのコードの配布可能なアーカイブ(.tar.bz2、.Zip、.jar、または適切なもの)をエクスポートする dist ターゲットをあなたのMakefile(または他のビルドシステム)に持つことです。偶然GNU autotoolsやPerlのMakeMakerシステムを使っているのなら、これは自動的にあると思います。そうでない場合は、追加することを強くお勧めします。
ETA(2012-09-06):うわー、厳しいマイナス投票。ソースコード管理ツールではなくビルドツールを使ってディストリビューションをビルドする方が良いと私は今でも信じています。私は構築ツールを使って成果物を構築することを信じています。私の現在の仕事では、私たちの主力製品はantターゲットで構築されています。私たちはソースコード管理システムの切り替えを行っている最中であり、このantターゲットの存在は移行の手間を1つ減らすことを意味します。
これにより、コミット範囲(CからG)のファイルがtarファイルにコピーされます。注:これはファイルをコミットするだけです。リポジトリ全体ではありません。 から少し修正された - ここ
コミット履歴の例
A - > B - > C - > D - > E - > F - > G - > H - > I
git diff-tree -r --no-commit-id --name-only --diff-filter=ACMRT C~..G | xargs tar -rf myTarFile.tar
-r - >サブツリーに再帰
--no-commit-id - > git diff-treeは、該当する場合にコミットIDを含む行を出力します。このフラグはコミットIDの出力を抑制しました。
--name-only - >変更されたファイルの名前だけを表示します。
--diff-filter = ACMRT - >これらのファイルのみを選択してください。 ファイルの完全なリストはこちらをご覧ください
C..G - >この範囲のコミットにあるファイル
C〜 - >コミットCからのファイルを含める.
| xargs tar -rf myTarFile - > tarへの出力
私はこれをdeployスクリプトに必要としていましたが、上記のアプローチをどれも使用できませんでした。代わりに、私は別の解決策を考え出しました:
#!/bin/sh
[ $# -eq 2 ] || echo "USAGE $0 REPOSITORY DESTINATION" && exit 1
REPOSITORY=$1
DESTINATION=$2
TMPNAME="/tmp/$(basename $REPOSITORY).$$"
git clone $REPOSITORY $TMPNAME
rm -rf $TMPNAME/.git
mkdir -p $DESTINATION
cp -r $TMPNAME/* $DESTINATION
rm -rf $TMPNAME
私が質問を理解したように、それはローカルリポジトリから状態を抽出するのではなく、履歴や他のブランチのデータを使わずに、サーバーから特定の状態だけをダウンロードすることです。
それはこのようにすることができます:
git clone -b someBranch --depth 1 --single-branch git://somewhere.com/repo.git \
&& rm -rf repo/.git/
--single-branch
はGit 1.7.10(2012年4月)から利用可能です。--depth
は(あった?) と伝えられています faultyですが、輸出の場合、言及された問題は重要ではないはずです。それを簡単な方法でやって、これは.bash_profileのための関数です、それは直接現在の場所でアーカイブを解凍します、最初にあなたの通常の[url:path]を最初に設定します。注:この機能を使用すると、クローン操作を避け、リモートレポジトリから直接取得します。
gitss() {
URL=[url:path]
TMPFILE="`/bin/tempfile`"
if [ "$1" = "" ]; then
echo -e "Use: gitss repo [tree/commit]\n"
return
fi
if [ "$2" = "" ]; then
TREEISH="HEAD"
else
TREEISH="$2"
fi
echo "Getting $1/$TREEISH..."
git archive --format=Zip --remote=$URL/$1 $TREEISH > $TMPFILE && unzip $TMPFILE && echo -e "\nDone\n"
rm $TMPFILE
}
.gitconfigのエイリアス、同じ設定が必要(.gitプロジェクトの中でコマンドを実行するには、TAKE CAREが常に以前にベースディレクトリにジャンプします ここで述べたように 、これが修正されるまで私は個人的に機能を好みます
ss = !env GIT_TMPFILE="`/bin/tempfile`" sh -c 'git archive --format=Zip --remote=[url:path]/$1 $2 \ > $GIT_TMPFILE && unzip $GIT_TMPFILE && rm $GIT_TMPFILE' -
私がこれを行うのを見たことがある(そしてウィンドウズでも同様に)はるかに簡単な方法はgit bundle
です:
git bundle create /some/bundle/path.bundle --all
詳細については、この回答を参照してください。 usbドライブを介してgitリポジトリをWindowsマシンからLinuxマシンにコピーする方法を教えてください。
エクスポートを作成したいマシン上にリポジトリのローカルコピーがある場合、私はうまく機能する別の解決策を持っています。この場合、このリポジトリディレクトリに移動して、次のコマンドを入力してください。
GIT_WORK_TREE=outputdirectory git checkout -f
これは、gitリポジトリでWebサイトを管理していて、/var/www/
でクリーンバージョンをチェックアウトしたい場合に特に便利です。この場合は、このコマンドを.git/hooks/post-receive
スクリプトに追加します(裸のリポジトリではhooks/post-receive
、この場合に適しています)。
プレフィックス(ディレクトリ名など)を追加しながらZipアーカイブにgitエクスポートする:
git archive master --prefix=directoryWithinZip/ --format=Zip -o out.Zip
サブモジュールも必要な場合は、これでうまくいくはずです。 https://github.com/meitar/git-archive-all.sh/wiki
私は私の.bashrcファイルに次のユーティリティ関数を持っています。それはgitリポジトリに現在のブランチのアーカイブを作成します。
function garchive()
{
if [[ "x$1" == "x-h" || "x$1" == "x" ]]; then
cat <<EOF
Usage: garchive <archive-name>
create Zip archive of the current branch into <archive-name>
EOF
else
local oname=$1
set -x
local bname=$(git branch | grep -F "*" | sed -e 's#^*##')
git archive --format Zip --output ${oname} ${bname}
set +x
fi
}
オプション1はあまり効果的ではないようです。クライアントにクローンを作成するスペースがない場合、および その後 で.git
フォルダーを削除します。
今日私は自分がこれをやろうとしているのに気づきました。そこではクライアントはほとんどスペースがないラズベリーパイです。さらに、私はまたリポジトリからいくつかの重いフォルダを除外したいと思います。
ここでの選択肢2などの回答は、このシナリオでは役に立ちません。どちらもgit archive
ではありません(.gitattributes
ファイルをコミットする必要があり、この除外をリポジトリに保存したくないため)。
ここで私は私の解決策を共有します、オプション3と似ていますが、git clone
の必要性なしで。
tmp=`mktemp`
git ls-tree --name-only -r HEAD > $tmp
rsync -avz --files-from=$tmp --exclude='fonts/*' . raspberry:
rsync
行をcompressと同等の行に変更することもgit archive
として機能しますが、( here のように)ある種の除外オプションがあります。