Git에서 파일을 이동하거나 이름을 바꾸고 기록을 유지할 수 있습니까?


667

Git에서 프로젝트 하위 트리의 이름을 바꾸거나 이동하고 싶습니다.

/project/xyz

/components/xyz

plain을 사용 git mv project components하면 xyz project가져 오기에 대한 모든 커밋 기록 이 사라집니다. 역사가 유지되도록 이것을 옮기는 방법이 있습니까?



2
방금 파일 시스템을 통해 파일 이동을 테스트했으며 (intellij를 통해) 커밋 한 후 기록을 볼 때 (intellij에서 다시) 전체 기록 (다른 위치에있을 때의 기록 포함)을 볼 수 있습니다. 나는 intellij가 특별히 특별한 일을하지 않는다고 가정하고 적어도 역사가 추적 될 수 있음을 아는 것이 좋습니다.
BT

디렉토리 이름 변경을 감지 할 때 Git이 따르는 규칙에 대해서는 아래 답변을
VonC

나는 여기에 답을 썼다. 나는 그것이 작동하기를 바랍니다. stackoverflow.com/questions/10828267/…
Mahmut EFE

답변:


651

힘내 커밋으로 사용 그래서 여부, 이름을 바꾸지 않고 작업을 지속를 감지 git mv하거나 mv중요하지 않습니다.

log명령은 --follow이름 바꾸기 작업 전에 기록을 계속 하는 인수를 취합니다 . 즉, 추론을 사용하여 유사한 내용을 검색합니다.

http://git-scm.com/docs/git-log

전체 기록을 조회하려면 다음 명령을 사용하십시오.

git log --follow ./path/to/file

63
이것이 성능 고려 사항이라고 생각합니다. 전체 기록이 필요하지 않으면 내용을 검색하는 데 시간이 더 오래 걸립니다. 가장 쉬운 방법은 별칭을 설정하고 git config alias.logf "log --follow"작성하는 것 git logf ./path/to/file입니다.
Troels Thomsen 2012

13
@TroelsThomsen 답변 과 연결된 Linus Torvalds 의이 이메일 은 이름 변경 등을 추적하는 것보다 훨씬 강력하기 때문에 Git의 의도적 인 디자인 선택임을 나타냅니다.
Emil Lundberg

127
이 답변은 약간 오해의 소지가 있습니다. Git은 "이름 변경을 감지하지만"게임에서 매우 늦습니다. 문제는 Git이 이름 변경을 추적하는 방법을 묻는 것입니다.이를 읽는 사람은 Git이 자동으로 이름을 감지하고 기록한다는 것을 쉽게 유추 할 수 있습니다. 그렇지 않습니다. Git은 실제로 이름 변경을 처리하지 않으며, 대신 무슨 일이 있었는지 알아 내려고 노력하는 병합 / 로그 도구가 있습니다. Linus는 왜 git이 올바른 방법으로 절대 이름을 바꾸지 말아야하는지에 대해 잘못하지만 격렬한 주장을하고 있습니다. 그래서 우리는 여기에 붙어 있습니다.
Chris Moschini

29
중요 사항 : 예를 들어 Java 패키지 이름을 바꾸는 동안 디렉토리 이름을 바꾸는 경우 먼저 'git mv {old} {new}'명령에 대해 두 번째 커밋을 실행하고 두 번째 커밋을 실행해야합니다. 변경된 패키지 디렉토리. 그렇지 않으면 git은 --follow 매개 변수를 사용해도 개별 파일을 추적 할 수 없습니다.
nn4l

44
Linus는 실수를 거의하지 않지만 이것은 하나의 실수로 보입니다. 단순히 폴더 이름을 바꾸면 거대한 델타가 GitHub에 업로드됩니다. 폴더 이름을 바꾸는 데주의를 기울여야하지만 프로그래머에게는 꽤 큰 스트레이트 재킷입니다. 때때로, 나는 무언가의 의미를 재정의하거나 물건이 분류되는 방식을 바꾸어야합니다. Linus : "즉, 옳습니다. 항상 옳지 만 때로는 다른 때보 다 옳습니다. 그리고 '파일이 중요하지 않습니다'라고 말할 때 정말 옳습니다 ( tm). " ... 그것에 대한 의심이 있습니다.
Gabe Halsmer

94

파일의 이름을 바꾸고 히스토리를 그대로 유지하는 것이 가능 하지만 저장소의 전체 히스토리에서 파일 이름이 변경됩니다. 이것은 아마도 강박적인 git-log-lovers에게만 해당되며 다음을 포함하여 몇 가지 심각한 의미를 갖습니다.

  • Git을 사용하는 동안 가장 중요하지 않은 공유 기록을 다시 작성할 수 있습니다. 다른 사람이 저장소를 복제 한 경우이를 수행하면 중단됩니다. 두통을 피하기 위해 다시 복제해야합니다. 이름 바꾸기가 충분히 중요한 경우에는 문제가되지 않지만 신중하게 고려해야합니다. 결국 전체 오픈 소스 커뮤니티를 혼란스럽게 할 수 있습니다!
  • 리포지토리 기록에서 이전 이름을 사용하여 파일을 참조한 경우 이전 버전을 효과적으로 손상시키는 것입니다. 이를 해결하려면 좀 더 후프 점프를해야합니다. 불가능하지 않고 지루하고 가치가 없습니다.

지금, 당신은 여전히 ​​나와 함께 있기 때문에, 당신은 아마도 완전히 고립 된 파일의 이름을 바꾸는 솔로 개발자 일 것입니다. filter-tree!를 사용하여 파일을 이동합시다 .

파일 old을 폴더로 이동 dir하고 이름을 지정 한다고 가정하십시오.new

이것은로 할 수 git mv old dir/new && git add -u dir/new있지만 역사를 깨뜨립니다.

대신 :

git filter-branch --tree-filter 'if [ -f old ]; then mkdir dir && mv old dir/new; fi' HEAD

것이다 다시 각 반복에 대한 틱으로 명령을 실행하는 모든이 지점에서 커밋. 이렇게하면 많은 것들이 잘못 될 수 있습니다. 나는 보통 파일이 존재하는지 (그렇지 않으면 아직 움직이지 않는지) 테스트 한 다음 필요한 단계를 수행하여 나무를 내 마음에 들게합니다. 여기에서 파일에 대한 참조를 변경하기 위해 파일을 sed 할 수 있습니다. 몸을 녹여 라! :)

완료되면 파일이 이동되고 로그가 그대로 유지됩니다. 당신은 닌자 해적처럼 느껴집니다.

또한; mkdir 디렉토리는 파일을 새 폴더로 이동하는 경우에만 필요합니다. 경우 역사의 앞부분이 폴더의 생성을 피할 파일이 존재보다.


57
강박적인 git-log-lover로서, 나는 이것을 가지 않을 것입니다. 그 시점에서 파일 이름이 지정되지 않았으므로 기록에는 존재하지 않는 상황이 반영됩니다. 과거에 어떤 테스트가 깨질 지 누가 알겠습니까? 이전 버전을 깨뜨릴 위험은 거의 모든 경우에 가치가 없습니다.
Vincent

7
@Vincent 당신은 절대적으로 맞습니다. 그리고이 솔루션의 가능성이 적절하지 않다는 것에 대해 최대한 명확하게 노력했습니다. 또한이 경우 "역사"라는 단어의 두 가지 의미에 대해 이야기하고 있다고 생각합니다.
Øystein Steimler

6
나는 이것이 필요할 수있는 상황이 있다는 것을 알았습니다. 개인 지사에서 무언가를 개발했다고 가정 해 봅시다. 그러나 파일 이름이 적절하지 않다는 것을 알았으므로 개인 브랜치 전체를 위해 파일 이름을 변경했습니다. 그렇게하면 깨끗하고 적절한 기록을 유지할 수 있고 처음부터 올바른 이름을 가질 수 있습니다.
user2291758

3
@ user2291758 이것이 나의 유스 케이스입니다. 이보다 강력한 git 명령은 위험하지만 그렇다고해서 자신이하는 일을 안다고해서 매우 유능한 사용 사례가없는 것은 아닙니다!
philix

1
가능한 경우 --index-filter모든 커밋마다 트리를 체크 아웃하고 다시 체크인 할 필요가 없으므로 for 이름 바꾸기를 사용하는 것이 훨씬 빠릅니다. --index-filter각 커밋 인덱스에서 직접 작동합니다.
Thomas Guyot-Sionnest

87

아니.

짧은 대답은 NO 입니다. Git에서 파일 이름을 바꾸고 기록을 기억할 수는 없습니다. 그리고 그것은 고통입니다.

소문은 효과가 git log --follow--find-copies-harder있지만 파일 내용이 전혀 변경되지 않았고로 이동 한 경우에도 작동하지 않습니다 git mv.

(처음에 나는 이름을 변경하고 힘내 혼란 수도 업데이트 패키지 하나의 작업에서, 이클립스를 사용했다. 그러나 그것은 할 수있는 매우 일반적인 일이다. --followA는 경우에만 작업에 보인다 mv수행 한 후 commit와는 mv너무 멀리하지 않습니다.)

Linus는 개별 파일을 추적 할 필요없이 소프트웨어 프로젝트의 전체 내용을 전체적으로 이해해야한다고 말합니다. 슬프게도 내 작은 뇌는 그렇게 할 수 없습니다.

많은 사람들이 Git이 자동으로 움직임을 추적한다는 진술을 무의식적으로 반복했다는 것은 정말 성가신 일 입니다. 그들은 내 시간을 낭비했다. 힘내는 그런 일을하지 않습니다. 의도적으로 (!) Git은 움직임을 전혀 추적하지 않습니다.

내 해결책은 파일 이름을 원래 위치로 다시 바꾸는 것입니다. 소스 제어에 맞게 소프트웨어를 변경하십시오. Git을 사용하면 처음으로 "git"해야 할 것 같습니다.

불행히도, 그것은 Eclipse를 깨뜨립니다 --follow. git log --follow복잡한 이름 변경 내역이있는 파일의 전체 기록을 표시하지 않는 경우도 git log있습니다. (왜 그런지 모르겠습니다.)

(뒤로 돌아가서 오래된 작업을 다시 시작하는 영리한 해킹이 있지만 다소 무섭습니다. GitHub-Gist : emiller / git-mv-with-history 참조 )


2
나는 당신이 맞다고 믿는다. Laravel 5 프로젝트의 소스를 다시 포맷하기 위해 php-cs-fixer를 사용하려고했지만 앱 폴더의 소문자 값과 일치하도록 네임 스페이스 절의 대문자를 변경해야합니다. 그러나 네임 스페이스 (또는 작곡가 자동로드)는 CamelCase에서만 작동합니다. 폴더의 대문자를 앱으로 변경해야하지만 변경 사항이 손실됩니다. 이것은 가장 간단한 예이지만, git 휴리스틱이 가장 간단한 이름 변경조차도 어떻게 따라갈 수 없는지 보여줍니다 (--follow 및 --find-copies-harder가 예외가 아닌 규칙이어야 함).
잭 모리스

6
git -1, subversion +1
Cosmin

아직도 그래요? 그래서 지금은 tfs를 유지 해야하는 더 큰 이유가 있습니다. 이동하거나 이름을 바꾼 파일의 기록을 유지하는 것은 큰 프로젝트에서 필수적입니다.
Cesar

"로그를 볼 때 후속의 이름 변경"을 "역사를 기억"에 의해 @Cesar하면, 그는 (우리가 관심을 가져야 만 유용한 것입니다) 의미, 다음이 없었다 결코 사실! Git은 이름을 "기록"하지 않지만 도구는 쉽게 이름을 감지하여 이름과 이동을 알려줍니다. 누군가에게 "작동하지 않는"경우 사용중인 도구를 변경해야합니다. 이 기능이있는 훌륭한 Git GUI 가 많이 있습니다 .
Mohammad Dehghan

짧은 대답은 예입니다. Git 최신 버전은 "git log --follow"도 지원합니다. @MohammadDehghan에 동의합니다.
인성

42
git log --follow [file]

이름 변경을 통해 기록을 표시합니다.


29
파일 수정을 시작하기 전에 이름 바꾸기 만 커밋해야합니다. 셸에서 파일을 이동 한 다음 변경하면 모든 베팅이 해제됩니다.
yoyo

22
@yoyo : git이 이름 바꾸기를 추적하지 않기 때문에 감지합니다. A는 git mv기본적으로 git rm && git add. 파일 이름이 90 % 일 때 파일 이름을 바꾸는 것으로 간주하는 -M90/ 와 같은 옵션이 있습니다 --find-renames=90.
vdboor 2016 년

22

나는한다:

git mv {old} {new}
git add -u {new}

3
-u는 나를 위해 아무것도하지 않는 것 같습니다. 역사를 업데이트한다고 가정합니까?
jeremy

1
아마도 당신은 -A대신 행동을 원 하십니까? 다시 여기를 참조 : git-scm.com/docs/git-add
제임스 M. 그린

1
파일을 추가하지만 기록을 업데이트하지 않으므로 'git log file name'에 전체 기록이 표시됩니다. --follow 옵션을 계속 사용하는 경우 전체 기록 만 표시합니다.
jeremy

3
include 디렉토리 (git mv가 아닌 mv 사용)를 이동시킨 다음 복잡한 리팩터링을 수행 한 다음 이름이 바뀐 파일 내에서 #include 경로를 많이 변경했습니다. git은 역사를 추적하기에 충분한 유사성을 찾을 수 없습니다. 그러나 git add -u는 내가 필요한 것입니다. 자식 상태는 이제 "삭제됨"과 "새 파일"을 표시하기 전에 "이름이 바뀐"상태를 나타냅니다.
AndyJost

1
의 목적을 다루는 SO에 대한 많은 질문이 git add -u있습니다. Git 문서는 도움이되지 않는 경향이 있으며 마지막으로보고 싶은 곳입니다. 다음 git add -u은 실제로 작동하는 게시물입니다 : stackoverflow.com/a/2117202 .
nobar

17

Git에서 프로젝트 하위 트리의 이름을 바꾸거나 이동하고 싶습니다.

/project/xyz

/ components / xyz

plain을 사용 git mv project components하면 xyz프로젝트의 모든 커밋 기록 이 손실됩니다.

Git은 디렉토리 rename감지 하므로 더 잘 문서화 되므로 아니오 (8 년 후, Git 2.19, 2018 년 3 분기 2018) .

참조 b00bf1c 커밋 , 1,634,688 커밋 , 0661e49 커밋 , 4d34dff 커밋 , 983f464 커밋 , c840e1a 커밋 , 9,929,430 커밋 (2018 6월 27일), 및 d4e8062 커밋 , 5dacd4a 커밋 에 의해 (2018 6월 25일를) 엘리야 Newren ( newren) .
( Junio ​​C gitsterHamano 에 의해 병합 - 커밋 0ce5a69 , 2018 년 7 월 24 일)

이제 설명되어 있습니다 Documentation/technical/directory-rename-detection.txt:

예:

때 모든 x/a, x/bx/c이동 한 z/a, z/b그리고 z/c이 가능성이 있는지, x/d그 사이에 추가도로 이동할 것이다 z/d전체 디렉토리 '라는 힌트를 취함으로써 x'이동 '을 z'.

그러나 그들은 다음과 같은 다른 많은 경우입니다.

히스토리의 한쪽은 이름이 바뀌고 x -> z다른 쪽은 일부 파일의 이름이로 바뀌어 x/e병합에서 전이적인 이름 바꾸기를 수행해야합니다.

디렉토리 이름 변경 탐지를 단순화하기 위해 Git은 이러한 규칙을 시행합니다.

디렉토리 이름 바꾸기 감지가 적용되는 경우 몇 가지 기본 규칙이 제한됩니다.

  1. 주어진 디렉토리가 여전히 병합의 양쪽에 존재하는 경우, 이름이 변경된 것으로 간주하지 않습니다.
  2. 이름을 바꾼 파일 중 일부에 파일이나 디렉토리가있는 경우 (또는 서로 방해가되는 경우) 해당 하위 경로의 디렉토리 이름을 "끄기"하고 충돌을 사용자에게보고하십시오. .
  3. 히스토리의 다른 쪽에서 디렉토리의 이름을 히스토리의 이름이 바뀐 경로로 바꾼 경우, 내재 된 디렉토리 이름 바꾸기에 대해 다른 쪽의 히스토리에서 해당 이름 바꾸기를 무시하십시오 (그러나 사용자에게 경고).

에서 많은 테스트를 볼 수 t/t6043-merge-rename-directories.sh있으며 다음을 지적합니다.

  • a) 이름 변경으로 디렉토리를 둘 이상의 다른 디렉토리로 분할하면 이름이 가장 많은 디렉토리가 "wins"입니다.
  • b) 경로가 병합의 양쪽에있는 이름 변경의 소스 인 경우 경로에 대한 디렉토리 이름 감지를 피하십시오.
  • c) 히스토리의 다른 쪽이 이름 바꾸기를 수행하는 것이면 내재적 디렉토리 이름 변경 만 디렉토리에 적용하십시오.

15

객관적인

  • 사용 ( Smar 에서 영감을 얻어 Exherbo 에서 빌림 )git am
  • 복사 / 이동 된 파일의 커밋 히스토리 추가
  • 한 디렉토리에서 다른 디렉토리로
  • 또는 한 저장소에서 다른 저장소로

한정

  • 태그 및 분기는 유지되지 않습니다
  • 경로 파일 이름 바꾸기 (디렉토리 이름 바꾸기)

요약

  1. 를 사용하여 이메일 형식으로 내역 추출
    git log --pretty=email -p --reverse --full-index --binary
  2. 파일 트리 재구성 및 파일 이름 업데이트
  3. 다음을 사용하여 새 기록 추가
    cat extracted-history | git am --committer-date-is-author-date

1. 이메일 형식으로 기록을 추출

예 : 추출물의 역사 file3, file4그리고file5

my_repo
├── dirA
│   ├── file1
│   └── file2
├── dirB            ^
│   ├── subdir      | To be moved
│   │   ├── file3   | with history
│   │   └── file4   | 
│   └── file5       v
└── dirC
    ├── file6
    └── file7

대상 설정 / 청소

export historydir=/tmp/mail/dir       # Absolute path
rm -rf "$historydir"    # Caution when cleaning the folder

이메일 형식으로 각 파일의 히스토리 추출

cd my_repo/dirB
find -name .git -prune -o -type d -o -exec bash -c 'mkdir -p "$historydir/${0%/*}" && git log --pretty=email -p --stat --reverse --full-index --binary -- "$0" > "$historydir/$0"' {} ';'

불행하게도 옵션 --follow또는 --find-copies-harder함께 사용할 수 없습니다 --reverse. 파일 이름이 변경 될 때 (또는 상위 디렉토리 이름이 변경 될 때) 히스토리가 잘리는 이유입니다.

이메일 형식의 임시 기록 :

/tmp/mail/dir
    ├── subdir
    │   ├── file3
    │   └── file4
    └── file5

Dan Bonachea 는 첫 번째 단계에서 git log 생성 명령의 루프를 뒤집을 것을 제안합니다. 파일 당 한 번 git log를 실행하는 대신 명령 행에서 파일 목록으로 정확히 한 번 실행하고 단일 통합 로그를 생성하십시오. 이 방법으로 여러 파일을 수정하면 결과에서 단일 커밋이 유지되고 모든 새 커밋은 원래의 상대 순서를 유지합니다. (현재 통일 된) 로그에 파일 이름을 다시 쓸 때 아래 두 번째 단계의 변경도 필요합니다.


2. 파일 트리 재구성 및 파일 이름 업데이트

이 다른 리포지토리에서이 세 파일을 이동한다고 가정합니다 (동일한 리포지토리 일 수 있음).

my_other_repo
├── dirF
│   ├── file55
│   └── file56
├── dirB              # New tree
│   ├── dirB1         # from subdir
│   │   ├── file33    # from file3
│   │   └── file44    # from file4
│   └── dirB2         # new dir
│        └── file5    # from file5
└── dirH
    └── file77

따라서 파일을 재구성하십시오.

cd /tmp/mail/dir
mkdir -p dirB/dirB1
mv subdir/file3 dirB/dirB1/file33
mv subdir/file4 dirB/dirB1/file44
mkdir -p dirB/dirB2
mv file5 dirB/dirB2

귀하의 임시 이력은 다음과 같습니다.

/tmp/mail/dir
    └── dirB
        ├── dirB1
        │   ├── file33
        │   └── file44
        └── dirB2
             └── file5

기록 내에서 파일 이름도 변경하십시오.

cd "$historydir"
find * -type f -exec bash -c 'sed "/^diff --git a\|^--- a\|^+++ b/s:\( [ab]\)/[^ ]*:\1/$0:g" -i "$0"' {} ';'

3. 새로운 역사를 적용

다른 저장소는 다음과 같습니다.

my_other_repo
├── dirF
│   ├── file55
│   └── file56
└── dirH
    └── file77

임시 히스토리 파일에서 커밋을 적용하십시오.

cd my_other_repo
find "$historydir" -type f -exec cat {} + | git am --committer-date-is-author-date

--committer-date-is-author-date원래 커밋 타임 스탬프를 유지합니다 ( Dan Bonachea 의 의견).

다른 레포는 지금 :

my_other_repo
├── dirF
│   ├── file55
│   └── file56
├── dirB
│   ├── dirB1
│   │   ├── file33
│   │   └── file44
│   └── dirB2
│        └── file5
└── dirH
    └── file77

git status푸시 될 준비가 된 커밋의 양을 보는 데 사용 하십시오 :-)


추가 트릭 : repo 내에서 이름이 바뀌거나 이동 된 파일 확인

이름이 바뀐 파일을 나열하려면 다음을 수행하십시오.

find -name .git -prune -o -exec git log --pretty=tformat:'' --numstat --follow {} ';' | grep '=>'

추가 사용자 정의 : git log옵션 --find-copies-harder또는을 사용 하여 명령 을 완료 할 수 있습니다 --reverse. cut -f3-완전한 패턴 '{. * =>. *}'를 사용 하고 grepping 하여 처음 두 열을 제거 할 수도 있습니다 .

find -name .git -prune -o -exec git log --pretty=tformat:'' --numstat --follow --find-copies-harder --reverse {} ';' | cut -f3- | grep '{.* => .*}'

4
BEWARE :이 기술은 2 개 이상의 파일을 변경하는 커밋을 별도의 조각난 커밋으로 분할하고 파일 이름을 기준으로 순서를 스크램블합니다 (따라서 하나의 원래 커밋 조각은 선형 히스토리에서 인접하지 않습니다). 따라서 결과 히스토리는 파일별로 "수정"됩니다. 둘 이상의 파일을 이동하는 경우 결과 히스토리에서 새 커미트 중 어느 것도 원래 리포지토리의 히스토리에 있던 이동 된 파일의 일관된 스냅 샷을 나타내지 않습니다.
Dan Bonachea

2
안녕하세요 @ DanBonachea. 흥미로운 의견에 감사드립니다. 이 기술을 사용하여 여러 파일을 포함하는 일부 저장소를 성공적으로 마이그레이션했습니다 (이름이 바뀐 파일 및 파일이 디렉토리를 이동하더라도). 이 답변에서 무엇을 바꾸라고 제안하십니까? 이 답변의 맨 위에이 기술의 한계를 설명하는 WARNING 배너를 추가해야한다고 생각하십니까? 건배
올리버

2
1 단계에서 git log 생성 명령의 루프를 반전시켜 문제를 피하기 위해이 기술을 수정했습니다. 파일 당 한 번 git log를 실행하는 대신 명령 행에서 파일 목록으로 정확히 한 번만 실행하고 단일 통합 로그를 생성하십시오. 이렇게하면 수정에서 2 개 이상의 파일을 하나의 커밋으로 유지하고 모든 새 커밋은 원래의 상대 순서를 유지합니다. (현재 통합 된) 로그에서 파일 이름을 다시 쓸 때 2 단계에서 변경해야합니다. 또한 원래 커밋 타임 스탬프를 보존하기 위해 git am --committer-date-is-author-date를 사용했습니다.
Dan Bonachea

1
실험하고 공유해 주셔서 감사합니다. 다른 독자들을 위해 약간의 답변을 업데이트했습니다. 그러나 처리 과정을 테스트하는 데 시간이 걸렸습니다. 명령 행 예제를 제공하려면이 답변을 자유롭게 편집하십시오. 건배;)
올리버

4

이 다단계 프로세스를 따라 코드를 상위 디렉토리로 이동하고 기록을 유지했습니다.

0 단계 : 안전한 보관을 위해 '마스터'에서 '역사'분기 생성

1 단계 : git-filter-repo 도구를 사용하여 기록을 다시 씁니다. 아래의이 명령은 폴더 'FolderwithContentOfInterest'를 한 레벨 위로 이동하고 관련 커밋 히스토리를 수정했습니다.

git filter-repo --path-rename ParentFolder/FolderwithContentOfInterest/:FolderwithContentOfInterest/ --force

2 단계 :이 시점까지 GitHub 리포지토리의 원격 리포지토리 경로가 손실되었습니다. 원격 참조 추가

git remote add origin git@github.com:MyCompany/MyRepo.git

3 단계 : 저장소에서 정보 가져 오기

git pull

4 단계 : 로컬 손실 지점과 원점 지점 연결

git branch --set-upstream-to=origin/history history

5 단계 : 메시지가 표시되면 폴더 구조에 대한 주소 병합 충돌

6 단계 : 푸시 !!

git push

참고 : 수정 된 기록 및 이동 된 폴더는 이미 커밋 된 것으로 나타납니다. enter code here

끝난. 코드는 기록을 그대로 유지하면서 부모 / 원하는 디렉토리로 이동합니다!


2

Git의 핵심 인 Git 배관은 이름 변경을 추적하지 않지만, Git 로그 "porcelain"으로 표시 한 기록은 원하는 경우 이름을 감지 할 수 있습니다.

주어진 git log경우 -M 옵션을 사용하십시오.

자식 로그 -p -M

현재 버전의 Git.

이것은 다른 명령에서도 작동합니다 git diff.

비교를 다소 엄격하게하는 옵션이 있습니다. 파일을 크게 변경하지 않고 파일 이름을 바꾸면 Git 로그 및 친구가 이름을 쉽게 검색 할 수 있습니다. 이러한 이유로 일부 사람들은 한 커밋에서 파일 이름을 바꾸고 다른 커밋에서 파일을 변경합니다.

Git에 파일 이름이 바뀐 위치를 찾을 때마다 파일 사용 여부와 시간에 따라 CPU 사용 비용이 발생합니다.

특정 리포지토리에서 이름 변경 검색으로 기록을 항상보고 싶다면 다음을 사용할 수 있습니다.

자식 설정 diff.renames 1

한 디렉토리에서 다른 디렉토리로 이동하는 파일 감지됩니다. 예를 들면 다음과 같습니다.

commit c3ee8dfb01e357eba1ab18003be1490a46325992
Author: John S. Gruber <JohnSGruber@gmail.com>
Date:   Wed Feb 22 22:20:19 2017 -0500

    test rename again

diff --git a/yyy/power.py b/zzz/power.py
similarity index 100%
rename from yyy/power.py
rename to zzz/power.py

commit ae181377154eca800832087500c258a20c95d1c3
Author: John S. Gruber <JohnSGruber@gmail.com>
Date:   Wed Feb 22 22:19:17 2017 -0500

    rename test

diff --git a/power.py b/yyy/power.py
similarity index 100%
rename from power.py
rename to yyy/power.py

이 기능은 with뿐만 아니라 diff를 사용할 때마다 작동합니다 git log. 예를 들면 다음과 같습니다.

$ git diff HEAD c3ee8df
diff --git a/power.py b/zzz/power.py
similarity index 100%
rename from power.py
rename to zzz/power.py

시험판으로 기능 분기에서 한 파일을 약간 변경하고 커밋 한 다음 마스터 분기에서 파일 이름을 바꾸고 커밋 한 다음 파일의 다른 부분을 조금 변경하여 커밋했습니다. 피처 브랜치에 가서 마스터에서 병합 할 때 병합은 파일 이름을 바꾸고 변경 사항을 병합했습니다. 병합 결과는 다음과 같습니다.

 $ git merge -v master
 Auto-merging single
 Merge made by the 'recursive' strategy.
  one => single | 4 ++++
  1 file changed, 4 insertions(+)
  rename one => single (67%)

그 결과 파일 이름이 바뀌고 텍스트가 변경되는 작업 디렉토리가 생성되었습니다. 따라서 Git이 이름 변경을 명시 적으로 추적하지 않더라도 올바른 작업을 수행 할 수 있습니다.

이것은 오래된 질문에 대한 늦은 답변이므로 다른 답변은 당시 Git 버전에 맞았을 수 있습니다.


1

먼저 이름 바꾸기만으로 독립 실행 형 커밋을 만듭니다.

그런 다음 최종적으로 파일 내용이 변경되면 별도의 커밋이 적용됩니다.


1

디렉토리 또는 파일의 이름을 바꾸려면 (복잡한 경우에 대해 잘 모르므로 몇 가지주의 사항이있을 수 있습니다) :

git filter-repo --path-rename OLD_NAME:NEW_NAME

언급 된 파일의 디렉토리 이름을 바꾸려면 (콜백을 사용할 수 있지만 방법을 모르겠습니다) :

git filter-repo --replace-text expressions.txt

expressions.txt같은 줄로 채워진 파일입니다 literal:OLD_NAME==>NEW_NAME(Python의 RE를 사용 regex:하거나 with를 사용할 수 있습니다 glob:).

커밋 메시지에서 디렉토리 이름을 바꾸려면 :

git-filter-repo --message-callback 'return message.replace(b"OLD_NAME", b"NEW_NAME")'

파이썬의 정규 표현식도 지원되지만 수동으로 파이썬으로 작성해야합니다.

리포지토리가 원격 인 원본 저장소 인 경우 --force다시 쓰려면 강제 로 추가해야합니다 . (이 작업을 수행하기 전에 리포지토리의 백업을 만들 수 있습니다.)

참조를 유지하지 않으려면 (Git GUI의 분기 히스토리에 표시됨)을 추가해야합니다 --replace-refs delete-no-add.


0

다음 과 같이 파일을 이동 하고 스테이지하십시오.

git add .

커밋하기 전에 상태를 확인할 수 있습니다.

git status

표시됩니다 :

Changes to be committed:
  (use "git restore --staged <file>..." to unstage)
        renamed:    old-folder/file.txt -> new-folder/file.txt

Git 버전 2.26.1로 테스트했습니다.

GitHub 도움말 페이지 에서 추출되었습니다 .


-3

파일을 이동시킨 다음

git add -A

삭제 된 / 새 파일을 모두 새깅 영역에 넣습니다. 여기서 git은 파일이 이동되었음을 인식합니다.

git commit -m "my message"
git push

왜 그런지 모르겠지만 이것이 효과가 있습니다.


여기서 요령은 하나의 문자를 변경할 필요가 없다는 것입니다. 무언가를 변경하고 Ctrl + Z를 눌러도 기록이 손상됩니다. 이 경우 무언가를 쓰면 파일을 되돌리고 다시 옮기고 하나의 추가-> 커밋을하십시오.
Xelian
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.