git-mv의 목적은 무엇입니까?


287

내가 이해 한 바에 따르면, Git은 실제로 파일 이름 바꾸기 / 이동 / 복사 작업 을 추적 할 필요가 없으므로 git mv 의 실제 목적은 무엇입니까? 맨 페이지는 특별히 설명이 아닙니다 ...

더 이상 사용되지 않습니까? 일반 사용자가 사용하지 않는 내부 명령입니까?

답변:


390
git mv oldname newname

다음과 같은 속기입니다.

mv oldname newname
git add newname
git rm oldname

즉, 기존 경로와 새 경로 모두에 대한 색인을 자동으로 업데이트합니다.


38
또한 몇 가지 안전 장치가 내장되어 있습니다.
Jakub Narębski

6
감사합니다 @CharlesBailey-git은 newNameFile과 oldNameFile 파일을 다른 것으로 간주합니까? 그렇다면, 병합하려는 경우 어떻게됩니까? 분기 A에서 개미 프로젝트를 분기하고 분기 B를 작성한 다음 B에서 프로젝트를 처리한다고 가정하십시오. 파일 이름은 동일하지만 프로젝트 구조가 변경됨에 따라 다른 경로에 배치됩니다. 두 가지가 동시에 동시에 성장했다고 가정 해보십시오. 어떤 시점에서 프로젝트를 병합하려면 git이 파일 이름이 동일한 파일이라는 것을 어떻게 알 수 있습니까? ( "git mv"== "git add + git rm"인 경우)
Rose

2
@SergeyOrshanskiy 자동 감지 기능이 잘못되면이 기능 mv oldname newname; git add newname; git rm oldname도 제대로 작동하지 않습니다 git mv oldname newname( 이 답변 참조 ).
Ajedi32

5
참고 git mv로부터 약간 다른 mv oldname newname; git add newname; git rm oldname당신이하기 전에 파일을 변경 한 경우 점에서, git mv그것을 보내고, 그 변화가 당신까지 개최되지 않습니다 git add새 파일을.
Ajedi32

2
git mv는 파일 이름의 변경 (foo.txt에서 Foo.txt로)을 처리하기 때문에 다른 동작을하는 반면 (OSX에서는)
greg.kindel

66

로부터 공식 GitFaq :

힘내 이름 바꾸기 명령 git mv을 가지고 있지만, 그것은 단지 편리합니다. 효과는 파일을 제거하고 다른 이름과 동일한 내용을 가진 다른 파일을 추가하는 것과 구별 할 수 없습니다


8
파일 기록을 잃어 버리셨습니까? 나는 ... 가정 이름 변경은 해당 디렉토리에 대한 오래된 역사를 유지하는 것이었다
윌 핸콕

17
예, 아니오 위의 공식 GitFaq 링크에서 이름 변경에 대해 읽은 다음 Linus Torvalds의 긴 이메일에서 SCM 도구 추적 파일의 개념이 마음에 들지 않는 이유를 확인하십시오. permalink.gmane.org/gmane.comp.version-control.git/ 217
Adam Nofsinger

3
@ WillHancock git을 조금 더 사용했으며 더 명확하게 답변 할 수 있습니다 .git 클라이언트와 옵션에 따라 파일이 내부적으로 약간 변경되어 파일 이름이 바뀌면 파일 이름을지나 파일을 추적 할 수 있습니다. 이름을 바꿉니다. 파일을 너무 많이 변경하고 이름을 바꾸면 git에서 파일을 감지하지 못합니다. "아니오, 완전히 다른 파일이라고 생각할 수도 있습니다!"
Adam Nofsinger

7
링크가 죽었다는 @AdamNofsinger. 여기에 거울입니다 : web.archive.org/web/20150209075907/http://...은
칼 월시

2
git mv수동 접근 방식 사이의 동등성을 나타내는 공식 참조 (즉, FAQ보다 추력 가치가있는)가 있습니까? 에서 분명하지 않습니다 git help mv.
tvo December

40

힘내는 당신이하려는 일을 추측하려고합니다. 끊임없는 역사를 보존하기 위해 모든 노력을 기울이고 있습니다. 물론 완벽하지는 않습니다. 따라서 git mv의도를 명확하게하고 일부 오류를 피할 수 있습니다.

이 예를 고려하십시오. 빈 저장소로 시작해서

git init
echo "First" >a
echo "Second" >b
git add *
git commit -m "initial commit"
mv a c
mv b a
git status

결과:

# On branch master
# 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)
#
#   modified:   a
#   deleted:    b
#
# Untracked files:
#   (use "git add <file>..." to include in what will be committed)
#
#   c
no changes added to commit (use "git add" and/or "git commit -a")

자동 감지 실패 :( 또는 그렇지 않습니까?

$ git add *
$ git commit -m "change"
$ git log c

commit 0c5425be1121c20cc45df04734398dfbac689c39
Author: Sergey Orshanskiy <*****@gmail.com>
Date:   Sat Oct 12 00:24:56 2013 -0400

    change

그리고

$ git log --follow c

Author: Sergey Orshanskiy <*****@gmail.com>
Date:   Sat Oct 12 00:24:56 2013 -0400

    change

commit 50c2a4604a27be2a1f4b95399d5e0f96c3dbf70a
Author: Sergey Orshanskiy <*****@gmail.com>
Date:   Sat Oct 12 00:24:45 2013 -0400

    initial commit

대신 .git실험 해보십시오 (실험 할 때 폴더 를 삭제해야 함 ).

git init
echo "First" >a
echo "Second" >b
git add *
git commit -m "initial commit"
git mv a c
git status

여태까지는 그런대로 잘됐다:

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


git mv b a
git status

이제 아무도 완벽하지 않습니다.

# On branch master
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#   modified:   a
#   deleted:    b
#   new file:   c
#

정말? 하지만 물론...

git add *
git commit -m "change"
git log c
git log --follow c

... 결과는 위와 같습니다 --follow. 전체 기록 만 표시합니다.


두 옵션 중 하나라도 여전히 이상한 효과를 낼 수 있으므로 이름 변경에주의하십시오 . 예:

git init
echo "First" >a
git add a
git commit -m "initial a"
echo "Second" >b
git add b
git commit -m "initial b"

git mv a c
git commit -m "first move"
git mv b a
git commit -m "second move"

git log --follow a

commit 81b80f5690deec1864ebff294f875980216a059d
Author: Sergey Orshanskiy <*****@gmail.com>
Date:   Sat Oct 12 00:35:58 2013 -0400

    second move

commit f284fba9dc8455295b1abdaae9cc6ee941b66e7f
Author: Sergey Orshanskiy <*****@gmail.com>
Date:   Sat Oct 12 00:34:54 2013 -0400

    initial b

그것을 대조하십시오 :

git init
echo "First" >a
git add a
git commit -m "initial a"
echo "Second" >b
git add b
git commit -m "initial b"

git mv a c
git mv b a
git commit -m "both moves at the same time"

git log --follow a

결과:

commit 84bf29b01f32ea6b746857e0d8401654c4413ecd
Author: Sergey Orshanskiy <*****@gmail.com>
Date:   Sat Oct 12 00:37:13 2013 -0400

    both moves at the same time

commit ec0de3c5358758ffda462913f6e6294731400455
Author: Sergey Orshanskiy <*****@gmail.com>
Date:   Sat Oct 12 00:36:52 2013 -0400

    initial a

업이 ... 이제 역사는 다시 것입니다 초기 대신 초기 나 잘못된 것입니다. 우리가 한 번에 두 번 움직였을 때, Git은 혼란스러워지고 변경 사항을 제대로 추적하지 못했습니다. 그건 그렇고, 내 실험에서을 사용하는 대신 파일을 삭제 / 생성했을 때도 마찬가지였습니다 git mv. 조심해서 진행하십시오. 당신은 경고를 받았습니다 ...


5
자세한 설명은 +1입니다. 파일이 git으로 이동하면 로그 기록에서 발생할 수있는 문제를 찾고 있었으므로 귀하의 답변은 정말 흥미 롭습니다. 감사합니다! Btw, git에서 파일을 이동하는 동안 피해야 할 다른 함정을 알고 있습니까? (또는 당신이 지적 할 수있는 어떤 참조 .... 그것을 위해 매우 운이 좋은 인터넷 검색)
pabrantes

1
글쎄, 내 예는 비관적입니다. 파일이 비어 있으면 변경 내용을 제대로 해석하기가 훨씬 어렵습니다. 모든 이름 바꾸기 후에 커밋하면 괜찮을 것이라고 생각합니다.
osa

27

@Charles가 말했듯 git mv이 속기입니다.

여기서 실제 질문은 "다른 버전 제어 시스템 (예 : Subversion 및 Perforce)은 파일 이름 변경을 특별히 처리합니다. 왜 Git이 그렇지 않습니까?"

Linus는 http://permalink.gmane.org/gmane.comp.version-control.git/217 에서 특징적인 전술을 설명합니다 .

이 "트랙 파일"크랩을 중지하십시오. Git은 중요한 파일, 즉 "파일 모음"을 정확하게 추적 합니다 . 다른 것은 아무것도 없으며, 그것이 적절 하다고 생각 하더라도 세계관을 제한 할뿐입니다. CVS의 "주석"이라는 개념이 어떻게 사람들이 CVS를 사용하는지 제한하는 결과를 낳습니다. 나는 그것이 전혀 쓸모없는 쓰레기라고 생각하며, 내가 백만 번 더 유용하다고 생각하는 것을 묘사했습니다. 그리고 나는 잘못된 생각의 세계 모델로 내 생각을 제한하지 않기 때문에 정확하게 빠졌습니다 .


9

git mv위에서 언급하지 않은 다른 용도가 있습니다 .

발견 git add -p(git add의 패치 모드; http://git-scm.com/docs/git-add 참조 ) 이후, 인덱스에 추가 할 때 변경 사항을 검토하는 데 사용하고 싶습니다. 따라서 내 워크 플로는 (1) 코드 작업, (2) 검토 및 색인에 추가, (3) 커밋이됩니다.

어떻게 git mv맞습니까? 파일을 직접 이동 한 다음 git rmgit add 모든 변경 사항이 색인에 추가되고 git diff를 사용하여 변경 사항을 보는 것은 쉽지 않습니다 (커밋하기 전에). 사용 git mv하지만, 인덱스에 새 경로를 추가하지만, 따라서 수 있도록 파일에 대한 변경 사항 git diffgit add -p평소와 같이 작업 할 수 있습니다.


5

틈새 사례가 있습니다. git mv대소 문자를 구분하지 않는 파일 시스템에서 파일 이름의 대소 문자를 변경하려는 여전히 유용한 있습니다. APFS (mac) 및 NTFS (windows)는 기본적으로 대소 문자를 구분하지 않지만 대소 문자를 구분합니다.

greg.kindel은 CB Bailey의 답변에 대한 의견에서 이것을 언급합니다.

Mac에서 작업 Mytest.txt중이고 git 에서 파일을 관리 한다고 가정합니다 . 파일 이름을로 변경하려고합니다 MyTest.txt.

시도해 볼 수 있습니다 :

$ mv Mytest.txt MyTest.txt
overwrite MyTest.txt? (y/n [n]) y
$ git status
On branch master
Your branch is up to date with 'origin/master'.

nothing to commit, working tree clean

이런. Git은 파일에 어떤 변화가 있었음을 인정하지 않습니다.

파일 이름을 완전히 바꾸고 다시 이름을 바꾸면이 문제를 해결할 있습니다.

$ mv Mytest.txt temp.txt
$ git rm Mytest.txt
rm 'Mytest.txt'
$ mv temp.txt MyTest.txt
$ git add MyTest.txt 
$ git status
On branch master
Your branch is up to date with 'origin/master'.

Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

    renamed:    Mytest.txt -> MyTest.txt

만세!

또는 다음을 사용하여 귀찮게 할 수도 있습니다 git mv.

$ git mv Mytest.txt MyTest.txt
$ git status
On branch master
Your branch is up to date with 'origin/master'.

Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

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