web-dev-qa-db-ja.com

Gitのフォルダー構造で変更および追加されたファイルのみをエクスポートする

特定のコミットで変更および追加されたファイルのリストを取得して、それらをエクスポートし、ファイル構造を持つパッケージを生成できるようにします。

アイデアは、パッケージを取得してサーバー上で展開することです。多くの理由で、レポジトリを自動的にプルするフックを作成できず、サーバーを最新の状態に保つ最も簡単な方法は、このパッケージを生成することです。

70
git diff-tree -r --no-commit-id --name-only --diff-filter=ACMRT $commit_id
  1. git diff-tree -r $commit_id

    指定されたコミットの差分を、その親(最上位ディレクトリだけでなく、すべてのサブディレクトリを含む)に取得します。

  2. --no-commit-id --name-only

    コミットSHA1を出力しません。完全な差分ではなく、影響を受けるファイルの名前のみを出力します。

  3. --diff-filter=ACMRT

    このコミットで追加、コピー、変更、名前変更されたファイル、またはタイプが変更されたファイル(ファイル→シンボリックリンクなど)のみを表示します。これにより、削除されたファイルは除外されます。


コメントから更新:
質問のコンテキストと以下のコメントに基づいて、次のコマンドを使用すると、ACMRTファイルを.tarファイルとそのフォルダー構造。

git diff-tree -r --no-commit-id --name-only --diff-filter=ACMRT $commit_id | tar -czf file.tgz -T -
94
git diff-tree -r --no-commit-id --name-only --diff-filter=ACMRT $commit_id | xargs tar -rf mytarfile.tar

これを締めくくるために、tarにパイプされたコマンドを次に示します。これにより、ファイルがtarアーカイブにエクスポートされます。

66
James Ehly

Windows 7で機能する1行のコマンドを次に示します。リポジトリの最上位フォルダーから実行します。

for/f "usebackq tokens = *"%A in( `git diff-tree -r --no-commit-id --name-only --diff-filter = ACMRT HEAD〜1 HEAD`)do echo FA | xcopy 「%〜fA」「C:\ git_changed_files \%A」

  • echo FAは、ファイルまたはディレクトリ(ファイル)のどちらをコピーするかについての避けられないxcopy質問と、ファイルの上書きについての考えられる質問(すべて上書き)に答えます。
  • sebackq gitコマンドの出力をdo句の入力として使用できます
  • HEAD〜1 HEADは、前のコミットと現在のHEAD間のすべての違いを取得します
  • %〜fA git出力を完全修飾パスに変換します(スラッシュをバックスラッシュに変更する必要があります)
  • C:\ git_changed_files \は、異なるすべてのファイルを見つける場所です
38
MM.

コミットハッシュがたとえばa9359f9の場合、次のコマンド:

git archive -o patch.Zip a9359f9 $(git diff --name-only a9359f9^..a9359f9)

コミットで変更されたファイルを抽出し、プロジェクトディレクトリ構造をそのままにしながらpatch.Zipに配置します。

少し冗長ですが、コミットハッシュは3回言及されていますが、私にはうまくいくようです。

ここにあります: http://tosbourn.com/2011/05/git/using-git-to-create-an-archive-of-changed-files/

29
Nicolas Dermine

Tortoise Git を使用してdiffをMS Windowsにエクスポートできます。

右クリックしてTortoiseGit>Show Logおよびログメッセージが開きます。

2つのリビジョンを選択して比較します。 の差が開きます。

ファイルを選択し、選択範囲を...にエクスポートします!

enter image description here

19
Wendel

テストサーバーを更新し、バージョン2.1以降に変更されたファイルを追加する必要がありました。

例えば:

tag_ver_2.1 = 1f72b38ad
tag_ver_2.2 = c1a546782

変更例を次に示します。

git diff-tree -r --no-commit-id --name-only c1a546782 1f72b38ad | xargs tar -rf test.tar
7
pietr

以下のコマンドは私のために働いた。

最後のコミットで変更されたファイルの違いが必要な場合:

git archive -o update.Zip HEAD $(git diff --name-only HEAD^)

または、2つの特定のコミットの違いが必要な場合:

git archive -o update.Zip 4d50f1ee78bf3ab4dd8e66a1e230a64b62c49d42 $(git diff --name-only 07a698fa9e5af8d730a8c33e5b5e8eada5e0f400)

または、コミットされていないファイルがある場合、gitの方法はすべてをコミットすることであり、ブランチは安価であることを忘れないでください:

git stash
git checkout -b feature/new-feature
git stash apply
git add --all
git commit -m 'commit message here'
git archive -o update.Zip HEAD $(git diff --name-only HEAD^)
2

Windowsで変更されたファイルをエクスポートするphpスクリプトを作成しました。 phpが設定されたlocalhost開発サーバーがある場合は、簡単に実行できます。最後のリポジトリを記憶し、常に同じフォルダーにエクスポートします。エクスポートフォルダは、エクスポートする前に常に空になります。また、削除されたファイルが赤で表示されるため、サーバー上で削除するものがわかります。

これらは2つのファイルなので、ここに投稿します。リポジトリが独自のフォルダのc:/ wwwの下にあり、 http:// localhost もc:/ wwwを指し、php対応であると仮定します。これらの2つのファイルをc:/ www/git-exportに入れましょう-

index.php:

<?php
/* create directory if doesn't exist */
function createDir($dirName, $perm = 0777) {
    $dirs = explode('/', $dirName);
    $dir='';
    foreach ($dirs as $part) {
        $dir.=$part.'/';
        if (!is_dir($dir) && strlen($dir)>0) {
            mkdir($dir, $perm);
        }
    }
}

/* deletes dir recursevely, be careful! */
function deleteDirRecursive($f) {

    if (strpos($f, "c:/www/export" . "/") !== 0) {
        exit("deleteDirRecursive() protection disabled deleting of tree: $f  - please edit the path check in source php file!");
    }

    if (is_dir($f)) {
        foreach(scandir($f) as $item) {
            if ($item == '.' || $item == '..') {
                continue;
            }

            deleteDirRecursive($f . "/" . $item);
        }    
        rmdir($f);

    } elseif (is_file($f)) {
        unlink($f);
    }
}

$lastRepoDirFile = "last_repo_dir.txt";
$repo = isset($_POST['repo']) ? $_POST['repo'] : null;


if (!$repo && is_file($lastRepoDirFile)) {
    $repo = file_get_contents($lastRepoDirFile);
}

$range = isset($_POST['range']) ? $_POST['range'] : "HEAD~1 HEAD";


$ini = parse_ini_file("git-export.ini");

$exportDir = $ini['export_dir'];
?>

<html>
<head>
<title>Git export changed files</title>
</head>

<body>
<form action="." method="post">
    repository: <?=$ini['base_repo_dir'] ?>/<input type="text" name="repo" value="<?=htmlspecialchars($repo) ?>" size="25"><br/><br/>

    range: <input type="text" name="range" value="<?=htmlspecialchars($range) ?>" size="100"><br/><br/>

    target: <strong><?=$exportDir ?></strong><br/><br/>

    <input type="submit" value="EXPORT!">
</form>

<br/>


<?php
if (!empty($_POST)) {

    /* ************************************************************** */
    file_put_contents($lastRepoDirFile, $repo); 

    $repoDir = $ini['base_repo_dir'] ."/$repo";
    $repoDir = rtrim($repoDir, '/\\');

    echo "<hr/>source repository: <strong>$repoDir</strong><br/>";
    echo "exporting to: <strong>$exportDir</strong><br/><br/>\n";


    createDir($exportDir);

    // empty export dir
    foreach (scandir($exportDir) as $file) {
        if ($file != '..' && $file != '.') {
            deleteDirRecursive("$exportDir/$file");
        }
    }

    // execute git diff
    $cmd = "git --git-dir=$repoDir/.git diff $range --name-only";

    exec("$cmd 2>&1", $output, $err);

    if ($err) {
        echo "Command error: <br/>";
        echo implode("<br/>", array_map('htmlspecialchars', $output));
        exit;
    }


    // $output contains a list of filenames with paths of changed files
    foreach ($output as $file) {

        $source = "$repoDir/$file";

        if (is_file($source)) {
            if (strpos($file, '/')) {
                createDir("$exportDir/" .dirname($file));
            }

            copy($source, "$exportDir/$file");
            echo "$file<br/>\n";

        } else {
            // deleted file
            echo "<span style='color: red'>$file</span><br/>\n";
        }
    }
}
?>

</body>
</html>

git-export.ini:

; path to all your git repositories for convenience - less typing
base_repo_dir = c:/www

; if you change it you have to also change it in the php script
; in deleteDirRecursive() function - this is for security
export_dir = c:/www/export

そして、ブラウザでlocalhost/git-export /をロードします。スクリプトは、常にc:/ www/exportにエクスポートするように設定されています。環境に合わせてすべてのパスを変更するか、ニーズに合わせてスクリプトを変更します。

これは、GitがインストールされていてgitコマンドがPATHにある場合に機能します。これは、Windows Gitインストーラーを実行するときに構成できます。

2
Lemon Juice

日付で始まる変更されたファイルをエクスポートするには:

  diff --stat @{2016-11-01} --diff-filter=ACRMRT --name-only | xargs tar -cf 11.tar

ショートカット(エイリアスを使用)

  git exportmdf 2016-11-01 11.tar

.gitconfigのエイリアス

  [alias]
  exportmdf = "!f() { \
    git diff --stat @{$1} --diff-filter=ACRMRT --name-only | xargs tar -cf $2; \
  }; f"
1
catalinp

これは、UnixとWindowsの両方で機能します。

git diff-tree -r --no-commit-id --name-only --diff-filter=ACMRT __1__.. | xargs cp --parents -t __2__

コマンドには2つのプレースホルダーがあります。あなたはあなたの目的のためにそれらを交換する必要があります:

  • __ 1 __:に置き換えますすべてのコミットの直前にコミットのIDをコミットエクスポートする(例:997cc7b6-コミットIDの後にその二重ドットを保持することを忘れないでください-これは意味します「このコミットよりも新しいコミットをすべて含める」)

  • __ 2 __:で置き換えるエクスポートする既存のパスファイル(例:../export_path/)

その結果、誰かがsvnリポジトリでtortoise svn exportsを使用することに慣れているかもしれないので、ファイルをフォルダー構造(zip/tarなし...)で取得します。

これは、たとえば、最後のコミットがほとんどない追加/変更されたファイルの手動デプロイを実行する場合に非常に便利です。そのため、これらのファイルをftpクライアント経由でコピーできます。

0
Skybamar

以前にも同様の問題に直面しました。簡単なシェルスクリプトを作成しました。

$git log --reverse commit_HashX^..commit_HashY --pretty=format:'%h'

上記のコマンドは、commit_HashXからcommit_HashYへのCommit Hash(Revision)を逆順で表示します。

 456d517 (second_hash)
 9362d03
 5362d03
 226x47a
 478bf6b (six_hash)

ここで、上記のコマンドを使用したメインシェルスクリプト。

commitHashList=$(git log --reverse $1^..$2 --pretty=format:'%h')
for hash in $commitHashList
do
    echo "$hash"
    git archive -o \Path_Where_you_want_store\ChangesMade.Zip $hash
done

このコードをexport_changes.shに追加します。ファイルを渡し、ハッシュをスクリプトにコミットします。

最初のcommit_hashが最初の引数であり、最後に変更をエクスポートする最後のcommit_hashであることを確認してください。

例:

$ sh export_changes.sh hashX hashY

このスクリプトをgitローカルディレクトリに配置するか、スクリプトでgitローカルディレクトリパスを設定します。 それが役立つことを願って..!

0
Raj Hawaldar

これは、フォルダ構造を使用して特定のコミットハッシュのファイルをコピーする小さなbash(Unix)スクリプトです。

ARRAY=($(git diff-tree -r --no-commit-id --name-only --diff-filter=ACMRT $1))
PWD=$(pwd)

if [ -d "$2" ]; then

    for i in "${ARRAY[@]}"
    do
        : 
        cp --parents "$PWD/$i" $2
    done
else
    echo "Chosen destination folder does not exist."
fi

「〜/ Scripts/copy-commit.sh」という名前のファイルを作成し、実行権限を付与します。

chmod a+x ~/Scripts/copy-commit.sh

次に、gitリポジトリのルートから:

~/Scripts/copy-commit.sh COMMIT_KEY ~/Existing/Destination/Folder/
0
Patrick.SE