자식에서 파일 이름 바꾸기 처리


440

git 에서 파일 이름을 바꿀변경 사항을 커밋하고 이름을 변경 한 다음 이름을 바꾼 파일을 준비해야 한다는 것을 읽었습니다 . Git은 파일을 새로운 추적되지 않은 파일로 보는 대신 내용에서 파일을 인식하고 변경 기록을 유지합니다.

그러나 오늘 밤 에이 작업을 수행하면 결국으로 되돌아갔습니다 git mv.

> $ git status
# On branch master
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#   modified:   index.html
#

Finder에서 내 스타일 시트의 이름을 iphone.css에서mobile.css

> $ git status
# On branch master
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#   modified:   index.html
#
# Changed but not updated:
#   (use "git add/rm <file>..." to update what will be committed)
#   (use "git checkout -- <file>..." to discard changes in working directory)
#
#   deleted:    css/iphone.css
#
# Untracked files:
#   (use "git add <file>..." to include in what will be committed)
#
#   css/mobile.css

git은 이제 하나의 CSS 파일을 삭제하고 새로운 파일을 추가했다고 생각합니다. 내가 원하는 것이 아니라 이름 바꾸기를 취소하고 자식이 작업을 수행하도록하십시오.

> $ git reset HEAD .
Unstaged changes after reset:
M   css/iphone.css
M   index.html

내가 시작한 곳으로 돌아갑니다.

> $ git status
# On branch master
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#   modified:   index.html
#

git mv대신 사용할 수 있습니다 .

> $ git mv css/iphone.css css/mobile.css
> $ git status
# On branch master
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#   renamed:    css/iphone.css -> css/mobile.css
#
# Changed but not updated:
#   (use "git add <file>..." to update what will be committed)
#   (use "git checkout -- <file>..." to discard changes in working directory)
#
#   modified:   index.html
#

우리가 좋아 보인다. 왜 Finder를 사용할 때 처음으로 이름 바꾸기를 인식하지 못했습니까?


29
Git은 파일이 아닌 컨텐츠를 추적하므로 인덱스를 올바른 상태로 만드는 방법에 관계없이 add+rm또는 mv동일한 결과를 생성합니다. 그런 다음 Git은 이름 변경 / 복사 감지 기능을 사용하여 이름이 변경되었음을 알립니다. 인용 한 출처도 정확하지 않습니다. 동일한 커밋에서 수정 + 이름 바꾸기 여부는 중요하지 않습니다. 수정과 이름 바꾸기를 모두 다르게 수행하면 이름 바꾸기 감지에서 이름이 변경 + 수정으로 표시되거나 수정이 전체 다시 쓰기 인 경우 추가 및 삭제 된 것으로 표시됩니다. 그것.
Cascabel

6
이것이 사실이라면 왜 Finder를 사용하여 이름을 바꾸어 감지하지 못했습니까?
Greg K

26
git mv old new색인을 자동으로 업데이트합니다. 당신이 망할 놈의 외부 이름을 변경하는 경우, 당신은을해야 할 것 git add newgit rm old인덱스에 대한 변경 사항을 무대. 완료하면 git status예상대로 작동합니다.
Chris Johnsen

4
방금 public_htmlgit에서 추적 되는 디렉토리 로 많은 파일을 옮겼습니다 . 수행 갖는 git add .하고 git commit, 아직 한 무리가 파일을 '삭제'했다 git status. 나는 a를 수행 git commit -a했고 삭제는 커밋되었지만 이제는 현재 존재하는 파일에 대한 기록이 없습니다 public_html. 이 작업 흐름은 내가 원하는만큼 부드럽 지 않습니다.
Greg K

답변:


352

대한 매뉴얼 페이지가 말한다git mv

성공적으로 완료되면 색인이 업데이트됩니다. […]

따라서 처음에는을 사용하여 색인을 직접 업데이트해야합니다 git add mobile.css. 그러나
git status 여전히 두 개의 다른 파일이 표시됩니다

$ git status
# On branch master
warning: LF will be replaced by CRLF in index.html
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#       modified:   index.html
#       new file:   mobile.css
#
# Changed but not updated:
#   (use "git add/rm <file>..." to update what will be committed)
#   (use "git checkout -- <file>..." to discard changes in working directory)
#
#       deleted:    iphone.css
#

을 실행하여 다른 출력을 얻을 수 있습니다. git commit --dry-run -a결과는 다음과 같습니다.

Tanascius@H181 /d/temp/blo (master)
$ git commit --dry-run -a
# On branch master
warning: LF will be replaced by CRLF in index.html
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#       modified:   index.html
#       renamed:    iphone.css -> mobile.css
#

우리 사이의 이러한 차이를 볼 이유는 정확히 말할 수 없어 git status하고
git commit --dry-run -a, 그러나 여기에서 힌트 라이너스 :

git은 내부적으로 "이름 변경 감지"전체를 신경 쓰지 않으며 , 이름 바꾸기로 수행 한 커밋 은 이름 바꾸기 를 표시 하는 휴리스틱과 완전히 독립적입니다 .

A dry-run는 실제 이름 바꾸기 메커니즘을 사용하지만 git status아마도 그렇지 않습니다.


1
당신이 한 단계를 언급하지 못했습니다 git add mobile.css. 그것 없이는 git status -a이전에 추적 된 iphone.css파일 의 제거만을 '보았지만'추적 되지 않은 새로운 mobile.css파일을 건드리지 않았을 것 입니다. 또한 git status -aGit 1.7.0 이상에서는 유효하지 않습니다. ""git status "는 더 이상"git commit --dry-run "이 아닙니다." 에 kernel.org/pub/software/scm/git/docs/RelNotes-1.7.0.txt . git commit --dry-run -a이 기능을 원하면 사용하십시오 . 다른 사람들이 말했듯이 인덱스를 업데이트 git status하면 OP가 기대하는대로 작동합니다.
Chris Johnsen 1

3
정상적인 git commit경우에는 이름이 바뀐 파일을 커밋하지 않으며 작업 트리는 여전히 동일합니다. git commit -agit의 워크 플로 / 사고 모델의 거의 모든 측면을 무너 뜨립니다. 모든 변경 사항이 적용됩니다. 파일 이름 만 바꾸고 index.html다른 커밋에서 변경 사항을 커밋하려면 어떻게합니까?
knittl

@Chris : 물론, 내가 mobile.css언급 했어야 할 것을 추가했습니다 . 그러나 그것은 내 대답의 요점입니다 .man 페이지는 the index is updated사용할 때라고 말합니다 git-mv. status -a명확하게 해 주셔서 감사합니다. git 1.6.4
tanascius

4
좋은 답변입니다! git status이름 변경을 감지하지 못한 이유를 파악하려고 벽에 머리를 대고 있었습니다. git commit -a --dry-run내 "새"파일을 추가 한 후 실행 하면 이름이 바뀌고 마침내 커밋에 대한 자신감이 생겼습니다.
stephen.hanson

1
자식 1.9.1에서 git status이제처럼 동작 git commit합니다.
Jacques René Mesrine

77

git이 파일을 이동으로 인식하기 전에 수정 된 두 파일을 인덱스에 추가해야합니다.

mv old newgit mv old newgit mv 의 유일한 차이점 은 파일을 인덱스에 추가한다는 것입니다.

mv old new다음 git add -A, 너무 일 것이다.

git add .인덱스에 제거를 추가하지 않기 때문에 사용할 수 는 없습니다.

"git add -A"와 "git add의 차이점을 참조하십시오 ."


3
git add -A그런 지름길을 찾고 있었기 때문에 매우 유용한 링크에 감사드립니다 !
PhiLho

5
자식 2, 참고 git add . 않는 인덱스에 제거를 추가합니다.
Nick McCurdy

19

가장 좋은 것은 직접 시도해 보는 것입니다.

mkdir test
cd test
git init
touch aaa.txt
git add .
git commit -a -m "New file"
mv aaa.txt bbb.txt
git add .
git status
git commit --dry-run -a

이제 git status와 git commit --dry-run -a는 git status가 bbb.txt를 새 파일로 표시하고 aaa.txt가 삭제되고 --dry-run 명령이 실제 이름을 바꾸는 두 가지 결과를 보여줍니다.

~/test$ git status

# On branch master
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#   new file:   bbb.txt
#
# Changes not staged for commit:
#   (use "git add/rm <file>..." to update what will be committed)
#   (use "git checkout -- <file>..." to discard changes in working directory)
#
#   deleted:    aaa.txt
#


/test$ git commit --dry-run -a

# On branch master
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#   renamed:    aaa.txt -> bbb.txt
#

이제 체크인을 진행하십시오.

git commit -a -m "Rename"

이제 파일의 이름이 바뀌었고 git status에 표시된 것이 잘못되었음을 알 수 있습니다.

이야기의 교훈 : 파일 이름이 바뀌 었는지 확실하지 않으면 "git commit --dry-run -a"를 발행하십시오. 파일 이름이 바뀌 었다는 메시지가 표시되면 계속 진행하십시오.


3
Git에 중요한 것은 둘 다 맞습니다 . 후자는 커미터가 볼 수 있듯이 어떻게 당신에게 더 가까이 있습니다. 이름 바꾸기와 삭제 + 생성 의 실제 차이점은 OS / 파일 시스템 수준 (예 : 동일한 inode #과 새로운 inode #)에서만 차이가 있으므로 Git은 그다지 신경 쓰지 않습니다.
Alois Mahdal

17

git 1.7.x의 경우 다음 명령이 효과적이었습니다.

git mv css/iphone.css css/mobile.css
git commit -m 'Rename folder.' 

원래 파일 (예 : css / mobile.css)이 이미 커밋 된 파일에 있었기 때문에 git add가 필요하지 않았습니다.


6
이. 다른 모든 대답은 어리 석고 불필요하게 복잡합니다. 이렇게하면 커밋간에 파일 히스토리가 유지되므로 파일 이름 변경 전후에 병합됩니다.
Phlucious

10

당신은에있는 git add css/mobile.css새 파일과 git rm css/iphone.css자식 그것에 대해 알 수 있도록. 그런 다음 동일한 출력을 표시합니다git status

상태 출력 (파일의 새 이름)에서 명확하게 볼 수 있습니다.

# Untracked files:
#   (use "git add <file>..." to include in what will be committed)

그리고 (이전 이름) :

# Changed but not updated:
#   (use "git add/rm <file>..." to update what will be committed)

나는 배후에서 git mv정확히 그것을하는 래퍼 스크립트 일뿐이라고 생각 합니다. 인덱스에서 파일을 삭제하고 다른 이름으로 추가하십시오.


나는 git rm css/iphone.css이것이 기존의 역사를 제거 할 것이라고 생각했기 때문에 내가해야한다고 생각하지 않았습니다 . 어쩌면 나는 git의 워크 플로우를 오해하고있을 것입니다.
Greg K

4
@Greg K : git rm기록을 제거하지 않습니다. 다음 커밋에 항목이 없도록 색인에서 항목 만 제거합니다. 그러나 조상 커밋에는 여전히 존재합니다. 당신이 혼란 스러울 수있는 것은 (예를 들어) git log -- new당신이 저지른 지점에서 멈출 것 git mv old new입니다. 이름 변경을 따르려면을 사용하십시오 git log --follow -- new.
Chris Johnsen

9

자식 관점에서 파일을 생각해 봅시다.

git은 파일에 대한 메타 데이터를 추적하지 않습니다.

귀하의 저장소는 (다른 것들 중에서)

$ cd repo
$ ls
...
iphone.css
...

그리고 git control하에 있습니다 :

$ git ls-files --error-unmatch iphone.css &>/dev/null && echo file is tracked
file is tracked

이것을 사용하여 테스트하십시오 :

$ touch newfile
$ git ls-files --error-unmatch newfile &>/dev/null && echo file is tracked
(no output, it is not tracked)
$ rm newfile

당신이 할 때

$ mv iphone.css mobile.css

자식 관점에서

  • iphone.css 가 없습니다 (삭제됨 -git 경고).
  • 새로운 파일 mobile.css가 있습니다.
  • 이 파일들은 완전히 관련이 없습니다.

따라서 git은 이미 알고있는 파일 ( iphone.css )과 감지하는 새 파일 ( mobile.css ) 에 대해 조언 하지만 파일이 색인에 있거나 HEAD git가 내용을 확인하기 시작할 때만 해당합니다.

현재 "iphone.css 삭제"또는 mobile.css 가 모두 색인에 없습니다.

색인에 iphone.css 삭제 추가

$ git rm iphone.css

git은 정확히 무슨 일이 있었는지 알려줍니다 : ( iphone.css 는 삭제됩니다. 더 이상 일어난 일은 없습니다)

그런 다음 새 파일 mobile.css 를 추가하십시오.

$ git add mobile.css

이번에는 삭제와 새 파일이 모두 색인에 있습니다. 이제 git은 컨텍스트가 동일하다는 것을 감지하고 이름을 바꿉니다. 실제로 파일이 50 % 유사하면 이름이 바뀌는 것을 감지 하여 작업 이름을 그대로 유지하면서 mobile.css 를 약간 변경할 수 있습니다 .

에서 재현 할 수 있음을 참조하십시오 git diff. 이제 파일이 색인에 있으므로를 사용해야합니다 --cached. mobile.css 를 약간 편집 하고 색인에 추가하고 다음의 차이점을 확인하십시오.

$ git diff --cached 

$ git diff --cached -M

-M에 대한 "이름 바꾸기 감지"옵션입니다 git diff. -M-M50%(50 % 이상의 유사성으로 인해 git이이를 이름 바꾸기로 표시 함)을 의미하지만 -M20%mobile.css를 많이 편집하면 이를 (20 %)로 줄일 수 있습니다 .


8

1 단계 : 파일 이름을 oldfile에서 newfile로 바꿉니다.

git mv #oldfile #newfile

2 단계 : 자식 커밋 및 주석 추가

git commit -m "rename oldfile to newfile"

3 단계 :이 변경 사항을 원격 서버로 푸시

git push origin #localbranch:#remotebranch

1
OP
Devrath

2 단계는 불필요합니다. 이후 git mv에는 새 파일이 이미 색인에 있습니다.
Alois Mahdal

7

Git은 파일을 새로운 추적되지 않은 파일로 보는 대신 내용에서 파일을 인식합니다.

그것이 당신이 잘못한 곳입니다.

파일을 추가 한 후에 만 해당 자식이 콘텐츠에서 파일을 인식합니다.


바로 그거죠. 단계별 git은 이름 바꾸기를 올바르게 표시합니다.
맥스 맥로드

3

파인더 이동 결과를 준비하지 않았습니다. Finder를 통해 이동 한 다음을 수행 git add css/mobile.css ; git rm css/iphone.css하면 git은 새 파일의 해시를 계산 한 다음 파일의 해시가 일치한다는 것을 깨닫고 이름을 바꿉니다.


2

예를 들어 실제로 파일 이름을 수동으로 바꿔야하는 경우. 스크립트를 사용하여 여러 파일의 배치 이름을 바꾼 다음 git add -A .나를 사용 했습니다.


2

Xcode 사용자의 경우 : Xcode에서 파일 이름을 바꾸면 배지 아이콘이 추가로 변경됩니다. XCode를 사용하여 커밋을 수행하면 실제로 새 파일을 만들고 기록을 잃게됩니다.

해결 방법은 쉽지만 Xcode를 사용하여 커밋하기 전에 수행해야합니다.

  1. 폴더에서 자식 상태를 수행하십시오. 단계적 변경 사항이 올바른지 확인해야합니다.

이름이 변경됨 : Project / OldName.h-> Project / NewName.h 이름이 변경되었습니다 : Project / OldName.m-> Project / NewName.m

  1. 커밋 -m '이름 변경'

그런 다음 XCode로 돌아 가면 배지가 A에서 M으로 변경된 것을 볼 수 있으며 xcode를 사용하여 변경 사항을 커밋하기 위해 저장됩니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.