특정 커밋에서 수정 및 추가 된 파일 목록을 가져 와서 내보내고 파일 구조로 패키지를 생성하고 싶습니다.
아이디어는 패키지를 가져 와서 서버에서 추출하는 것입니다. 여러 가지 이유로 리포지토리를 자동으로 가져 오는 후크를 만들 수 없으며 서버를 업데이트하는 가장 쉬운 방법은이 패키지를 생성하는 것입니다.
답변:
git diff-tree -r --no-commit-id --name-only --diff-filter=ACMRT $commit_id
git diff-tree -r $commit_id
:
주어진 커밋의 차이를 부모 (들) (상위 디렉토리뿐만 아니라 모든 하위 디렉토리 포함)로 가져갑니다.
--no-commit-id --name-only
:
커밋 SHA1을 출력하지 마십시오. 전체 diff 대신 영향을받는 파일의 이름 만 출력합니다.
--diff-filter=ACMRT
:
이 커밋에서 추가, 복사, 수정, 이름 변경 또는 유형이 변경된 파일 (예 : 파일 → 심볼릭 링크) 만 표시합니다. 삭제 된 파일은 제외됩니다.
주석 에서 업데이트 : 질문 컨텍스트와 아래 주석을 기반으로 다음 명령 ACMRT
을 사용하여 .tar
파일을 폴더 구조 의 파일로 가져올 수 있습니다 .
git diff-tree -r --no-commit-id --name-only --diff-filter=ACMRT $commit_id | tar -czf file.tgz -T -
git diff-tree -r --no-commit-id --name-only --diff-filter=ACMRT $commit_id | tar -czf file.tgz -T -
git diff-tree -r --no-commit-id --name-only --diff-filter=ACMRT $commit_id | xargs tar -rf mytarfile.tar
이를 마무리하기 위해 다음은 tar에 파이프 된 명령입니다. 파일을 tar 아카이브로 내 보냅니다.
다음은 Windows 7에서 작동하는 한 줄 명령입니다. 저장소의 최상위 폴더에서 실행하십시오.
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"
커밋 해시가 예를 들어 a9359f9 인 경우이 명령은 다음과 같습니다.
git archive -o patch.zip a9359f9 $(git diff --name-only a9359f9^..a9359f9)
프로젝트 디렉토리 구조는 그대로 유지하면서 커밋에서 수정 된 파일을 추출하여 patch.zip에 배치합니다.
약간 장황하면 커밋 해시가 세 번 언급되었지만 저에게는 작동하는 것 같습니다.
여기에있어 : http://tosbourn.com/2011/05/git/using-git-to-create-an-archive-of-changed-files/
function
에서 PowerShell을 단지 함수 이름에 명령을 줄이고 사용하는 $args
(가) 한 번만 해시를 커밋에 전달합니다. * nix에서는 셸 스크립팅을 사용하여 동일한 효과를 얻을 수 있습니다.
git archive -o patch.zip HEAD /**or a commit**/ $(git diff --name-only commit1 commit2)
합니다. archive
명령에 전달 된 커밋은 임의의 커밋 (대부분 HEAD 또는 이후 커밋) 일 수 있으며 파일은 해당 커밋 단계에서 체크 아웃 된 것처럼 가져옵니다. 전달 된 commit1 및 commit2 는 diff
가져올 파일 목록을 생성하는 데만 사용되며 가져올 파일의 버전에는 영향을주지 않습니다.
diff
세미콜론으로 명령을 반복 하십시오.git archive -o patch.zip HEAD /**or a commit**/ $(git diff --name-only commit1A commit1B; git diff --name-only commit2A commit2B; git diff --name-only commit3A commit3B)
git diff -z --name-only commit1 commit2 | xargs -0 git archive -o patch.zip HEAD
Tortoise Git 을 사용하여 diff 를 MS Windows로 내보낼 수 있습니다 .
나는 오른쪽 버튼으로 클릭하고 TortoiseGit > 로그 표시를 하고 로그 메시지가 공개됩니다.
두 버전을 선택하고 비교하십시오. 차이 가 열립니다.
파일을 선택하고 선택 항목을 ... 폴더로 내보내기 !
테스트 서버를 업데이트하고 버전 2.1 이후 변경된 파일을 추가해야했습니다.
나를 위해 James Ehly가 게시 한 것과 유사한 솔루션을 사용했지만 제 경우에는 두 개의 이전 태그-tag_ver_2.1 및 tag_ver_2.2의 유일한 커밋이 아닌 아카이브 패키지로 내보내고 싶었습니다.
예 :
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
아래 명령은 나를 위해 일했습니다.
마지막 커밋으로 변경된 파일의 차이를 원하는 경우 :
git archive -o update.zip HEAD $(git diff --name-only HEAD HEAD^)
또는 두 개의 특정 커밋 간의 차이를 원하는 경우 :
git archive -o update.zip sha1 $(git diff --name-only sha1 sha2)
또는 커밋되지 않은 파일이있는 경우 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 HEAD^)
Windows에서 변경된 파일을 내보내는 PHP 스크립트를 만들었습니다. PHP가 설정된 localhost 개발 서버가 있으면 쉽게 실행할 수 있습니다. 마지막 저장소를 기억하고 항상 동일한 폴더로 내 보냅니다. 내보내기 폴더는 내보내기 전에 항상 비워집니다. 또한 삭제 된 파일이 빨간색으로 표시되므로 서버에서 삭제할 항목을 알 수 있습니다.
이 파일은 두 개일 뿐이므로 여기에 게시하겠습니다. 저장소가 자체 폴더의 c : / www 아래에 있고 http : // localhost 도 c : / www를 가리키고 php가 활성화 되어 있다고 가정 해 보겠습니다 . 이 두 파일을 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 명령이 PATH에 있도록 Git을 설치 한 경우 작동합니다. Windows Git 설치 프로그램을 실행할 때 구성 할 수 있습니다.
다음은 폴더 구조로 주어진 커밋 해시에 대한 파일을 복사하는 작은 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/
나는 또한 이전에 비슷한 문제에 직면했습니다. 간단한 쉘 스크립트를 작성했습니다.
$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 로컬 디렉토리 경로를 설정하십시오. 도움이 되길 바랍니다 ..!
이것은 Unix와 Windows 모두에서 작동합니다.
git diff-tree -r --no-commit-id --name-only --diff-filter=ACMRT __1__.. | xargs cp --parents -t __2__
명령에는 두 개의 자리 표시자가 있습니다. 용도에 맞게 교체해야합니다.
__1__ : 내보내려는 모든 커밋 바로 직전에 커밋의 커밋 ID로 교체합니다 (예 : 997cc7b6-커밋 ID 뒤에 이중 점을 유지하는 것을 잊지 마세요. 이것은 "이 커밋보다 새로운 커밋을 모두 포함"을 의미합니다).
__2__ : 파일 을 내보낼 기존 경로 (예 : ../export_path/)로 바꿉니다.
결과적으로 누군가 svn 저장소에서 tortoise svn 내보내기 를 사용하는 데 익숙 할 수 있으므로 파일을 폴더 구조 (zip / tars 없음 ...)로 가져옵니다 .
예를 들어 마지막 커밋이 거의없는 추가 / 수정 파일을 수동으로 배포하려는 경우 매우 유용합니다. 따라서 ftp 클라이언트를 통해 이러한 파일을 복사 할 수 있습니다.