Git 복사 파일 기록 보존
나는 Git에서 다소 혼란스러운 질문이 있습니다.예를 들어, 내가 파일을 가지고 있다고 칩시다.dir1/A.txt
and 합니다.
는 그 파일을 파합니다야복사해로 .dir2/A.txt
(움직이지 않고 복사).나는 그것이 있다는 것을 알고 있습니다.git mv
명령이 합니다.dir2/A.txt
▁as▁▁history와 같은 dir1/A.txt
,그리고.dir1/A.txt
여전히 거기에 남아 있습니다.
업이트할없다습니이획계 업데이트를 할 계획이 .A.txt
일단 복사본이 생성되고 모든 향후 작업이 수행될 것입니다.dir2/A.txt
혼란스럽게 들리겠지만, 이 상황이 Java 기반 모듈(Mavenized Project)에 있으며 고객이 런타임에 두 가지 다른 버전을 사용할 수 있도록 코드의 새 버전을 만들어야 합니다. 정렬이 완료되면 첫 번째 버전은 제거됩니다.우리는 물론 메이븐 버전을 사용할 수 있습니다. 저는 Git의 초보자일 뿐이며 Git이 여기서 무엇을 제공할 수 있는지 궁금합니다.
당신이 해야 할 일은 다음과 같습니다.
- 파일을 두 개의 다른 위치로 이동합니다.
- 위와 같은 두 커밋을 병합합니다.
- 복사본 하나를 원래 위치로 다시 이동합니다.
은 역사적을 볼 수 입니다.git blame
및)git log
두에 해당합니다 두 파일 모두에 적용됩니다.
.foo
라고 하는bar
다음과 .
git mv foo bar
git commit
SAVED=`git rev-parse HEAD`
git reset --hard HEAD^
git mv foo copy
git commit
git merge $SAVED # This will generate conflicts
git commit -a # Trivially resolved like this
git mv copy foo
git commit
작동하는 이유
위의 명령을 실행한 후 다음과 같은 수정 내역이 표시됩니다.
( revision history ) ( files )
ORIG_HEAD foo
/ \ / \
SAVED ALTERNATE bar copy
\ / \ /
MERGED bar,copy
| |
RESTORED bar,foo
당신이 Git에게 Git의 역사를 물어볼 때.foo
다음과 같습니다.
- 에서 이름
copy
RESTOVEN , 합과복사이병원,이, - …을
copy
, Merged라는 이름의 Merged입니다. - 에서 이름
foo
ORIG_HEAD는 ALTERNACT입니다.
거기서부터 그것은 역사를 파헤칠 것입니다.foo
.
당신이 Git에게 Git의 역사를 물어볼 때.bar
다음과 같습니다.
- MARGEED와 RESTORENED 사이에는 변경 사항이 없습니다.
- …을
bar
MARGED의 부모로부터 . - 에서 이름
foo
ORIG_HEAD 사 SAVE 이와.
거기서부터 그것은 역사를 파헤칠 것입니다.foo
.
그렇게 간단하다.:)
추적 가능한 두 개의 파일 복사본을 허용할 수 있는 병합 상황에 Git을 강제로 적용하면 원본을 병렬로 이동하여 이 작업을 수행할 수 있습니다(곧 되돌립니다).
하위 버전과 달리 Git에는 파일별 기록이 없습니다.커밋 데이터 구조를 보면 이전 커밋과 이 커밋에 대한 새 트리 개체만 가리킵니다.커밋에 의해 변경되는 파일에 대한 명시적인 정보는 커밋 개체에 저장되지 않으며 이러한 변경 사항의 특성도 저장되지 않습니다.
변경 사항을 검사하는 도구는 휴리스틱을 기반으로 이름 변경을 탐지할 수 있습니다.예.git diff
선택권이 있습니다.-M
이름 바꾸기 탐지가 활성화됩니다.그래서 이름을 바꾼다면,git diff
하나의 파일이 삭제되고 다른 파일이 생성되었음을 표시할 수 있습니다.git diff -M
실제로 이동을 감지하고 그에 따라 변경 내용을 표시합니다( 참조).man git diff
자세한 내용은).
따라서 이는 변경사항을 커밋하는 방법이 아니라 나중에 커밋된 변경사항을 어떻게 보느냐의 문제입니다.
파일을 복사하고 추가한 후 커밋하기만 하면 됩니다.
cp dir1/A.txt dir2/A.txt
git add dir2/A.txt
git commit -m "Duplicated file from dir1/ to dir2/"
그런 다음 다음 명령은 전체 사전 복사 기록을 표시합니다.
git log --follow dir2/A.txt
원본 파일에서 상속된 줄별 주석을 보려면 다음을 사용합니다.
git blame -C -C -C dir2/A.txt
Git는 커밋 시간에 복사본을 추적하지 않고 대신 기록을 검사할 때 탐지합니다.git blame
그리고.git log
.
이 정보의 대부분은 Git를 사용하여 파일 복사 작업을 기록합니다.
여기서 피터의 답변을 약간 수정하여 재사용 가능하고 상호 작용하지 않는 셸 스크립트를 만들었습니다.git-split.sh
:
#!/bin/sh
if [[ $# -ne 2 ]] ; then
echo "Usage: git-split.sh original copy"
exit 0
fi
git mv "$1" "$2"
git commit -n -m "Split history $1 to $2 - rename file to target-name"
REV=`git rev-parse HEAD`
git reset --hard HEAD^
git mv "$1" temp
git commit -n -m "Split history $1 to $2 - rename source-file to temp"
git merge $REV
git commit -a -n -m "Split history $1 to $2 - resolve conflict and keep both files"
git mv temp "$1"
git commit -n -m "Split history $1 to $2 - restore name of source-file"
완벽하게 하기 위해 제어 및 제어되지 않는 파일로 가득 찬 전체 디렉터리를 복사하려면 다음을 사용할 수 있습니다.
git mv old new
git checkout HEAD old
제어되지 않은 파일은 복사되므로 다음과 같이 정리해야 합니다.
git clean -fdx new
이 경우 하드 드라이브를 변경하고(작업 복사본의 한 경로에서 다른 경로로 약 200개의 폴더/파일을 잘라내기/붙여넣기) 소스 트리(2.0.20.1)를 사용하여 탐지된 변경 사항을 모두 스테이징(한 번 추가, 한 번 제거)하고 추가 및 제거를 함께 스테이징하는 한,핑크 R 아이콘(이름 변경)으로 자동으로 단일 변경으로 결합됩니다.
한 번에 너무 많은 변경 사항이 있었기 때문에 SourceTree가 모든 변경 사항을 감지하는 속도가 약간 느려서 준비된 파일 중 일부는 단순히 추가(녹색 더하기) 또는 삭제(빨간색 빼기)하는 것처럼 보이지만, 파일 상태를 계속 새로 고치고 몇 분 후에 새로운 변경 사항이 나타날 때마다 계속 준비했습니다.모든 목록은 완벽했고 커밋할 준비가 되었습니다.
기록을 찾을 때 "이름 변경된 파일 따라하기" 옵션을 선택하면 기록이 있는지 확인합니다.
이 프로세스는 기록을 보존하지만 해결 방법이 거의 없습니다.
# make branchs to new files
$: git mv arquivos && git commit
# in original branch, remove original files
$: git rm arquivos && git commit
# do merge and fix conflicts
$: git merge branch-copia-arquivos
# back to original branch and revert commit removing files
$: git revert commit
언급URL : https://stackoverflow.com/questions/16937359/git-copy-file-preserving-history
'source' 카테고리의 다른 글
waitpid, wnohang, 추적되지 않은.사용 방법 (0) | 2023.06.26 |
---|---|
간단한 삽입 문을 사용하여 이진 파일 데이터를 이진 SQL 필드에 삽입하려면 어떻게 해야 합니까? (0) | 2023.06.26 |
vuex 알 수 없는 작업(또는 변환) 유형 (0) | 2023.06.26 |
Can I comment out a line in a .git/config file? (0) | 2023.06.26 |
"gitrm --dll x" vs "git reset head --x"? (0) | 2023.06.26 |