Git에서 폴더 구조로 수정 및 추가 된 파일 만 내보내기
특정 커밋에서 수정 및 추가 된 파일 목록을 가져 와서 파일을 내보내고 파일 구조로 패키지를 생성하고 싶습니다.
아이디어는 패키지를 가져 와서 서버에서 추출하는 것입니다. 여러 가지 이유로 리포지토리를 자동으로 가져 오는 후크를 만들 수 없으며 서버를 업데이트하는 가장 쉬운 방법은이 패키지를 생성하는 것입니다.
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 | 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"
- echo FA 는 파일을 복사하는지 디렉토리 (파일)를 복사하는지에 대한 불가피한 xcopy 질문과 파일 덮어 쓰기 (모두 덮어 쓰기)에 대한 가능한 질문에 답합니다.
- usebackq 를 사용하면 git 명령의 출력을 do 절의 입력으로 사용할 수 있습니다.
- HEAD ~ 1 HEAD 는 이전 커밋과 현재 HEAD의 모든 차이점을 가져옵니다.
- % ~ fA 는 git 출력을 정규화 된 경로로 변환합니다 (슬래시를 백 슬래시로 변경해야 함).
- C : \ git_changed_files \ 는 다른 모든 파일을 찾을 수있는 곳입니다.
커밋 해시가 예를 들어 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/
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
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로 내보내도록 설정되어 있습니다. 환경에 맞게 모든 경로를 변경하거나 필요에 맞게 스크립트를 수정하십시오.
This will work if you have Git installed so that the git command is in your PATH - this can be configured when you run the windows Git installer.
Below commands worked for me.
If you want difference of the files changed by the last commit:
git archive -o update.zip HEAD $(git diff --name-only HEAD HEAD^)
or if you want difference between two specific commits:
git archive -o update.zip sha1 $(git diff --name-only sha1 sha2)
or if you have uncommitted files, remember git way is to commit everything, branches are cheap:
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^)
To export modified files starting with a date:
diff --stat @{2016-11-01} --diff-filter=ACRMRT --name-only | xargs tar -cf 11.tar
Shortcut (use alias)
git exportmdf 2016-11-01 11.tar
Alias in .gitconfig
[alias]
exportmdf = "!f() { \
git diff --stat @{$1} --diff-filter=ACRMRT --name-only | xargs tar -cf $2; \
}; f"
Here is a small bash(Unix) script that I wrote that will copy files for a given commit hash with the folder structure:
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
Create a file named '~/Scripts/copy-commit.sh' then give it execution privileges:
chmod a+x ~/Scripts/copy-commit.sh
Then, from the root of the git repository:
~/Scripts/copy-commit.sh COMMIT_KEY ~/Existing/Destination/Folder/
I also faced a similar problem before. I wrote a simple Shell script.
$git log --reverse commit_HashX^..commit_HashY --pretty=format:'%h'
The above command will display Commit Hash(Revision) from commit_HashX to commit_HashY in reverse order.
456d517 (second_hash)
9362d03
5362d03
226x47a
478bf6b (six_hash)
Now the main Shell Script using above command.
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
Add this code to export_changes.sh. Now pass file and commit hashes to the script.
Make sure that initial commit_hash must be the first argument then last commit_hash up to which you want to export changes.
Example:
$sh export_changes.sh hashX hashY
Put this script into git local directory or set git local directory path in the script. Hope it Helps..!
This works for me for both Unix and Windows:
git diff-tree -r --no-commit-id --name-only --diff-filter=ACMRT __1__.. | xargs cp --parents -t __2__
There are two placeholders in the command. You need to replace them for your purpose:
__1__: replace with commit id of commit right before all of the commits you want to export (e.g. 997cc7b6 - don't forget to keep that doubledot after commit id - this means "involve all commits newer than this commit")
__2__: replace with existing path where you want to export your files (e.g. ../export_path/)
As a result you will get your files in a folder structure (no zips/tars...) as someone might be used to using tortoise svn exports in svn repositories.
This is for example pretty useful when you want to perform manual deploy of added/modified files of few last commits. So you can then just copy these files through ftp client.
'Programing' 카테고리의 다른 글
PHP에서 다차원 배열을 단순 배열로 "평탄화"하는 방법은 무엇입니까? (0) | 2020.10.28 |
---|---|
Android EditText 힌트 크기 (0) | 2020.10.28 |
인덱스로 std :: tuple 요소를 설정하는 방법은 무엇입니까? (0) | 2020.10.27 |
컴파일러 오류 "필수 라이브러리에 대한 아카이브를 읽을 수 없습니다"-Spring Tool Suite (0) | 2020.10.27 |
함수에 벡터 전달, 값 대 참조 C ++ (0) | 2020.10.27 |