programing

Git에서 파일 이름 변경 처리

bestprogram 2023. 5. 2. 23:05

Git에서 파일 이름 변경 처리

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

하지만, 오늘 밤 이것만 하는 것으로 저는 결국 돌아갔습니다.git mv.

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

파인더에서 스타일시트의 이름을 변경했습니다.iphone.cssmobile.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에게 작업을 맡깁시다.

> $ 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
#

괜찮은 것 같아요.그럼 왜 Git는 제가 Finder를 사용했을 때 처음으로 이름 변경을 인식하지 못했을까요?

위해서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 이름 메커니즘을 , 는 " 실이바을사동용는안하즘메니커꾸기름제동안▁uses▁thes는사▁mechanism하"git status아마 그렇지 않을 겁니다.

수정된 두 개의 파일을 인덱스에 추가해야 Git가 이동으로 인식할 수 있습니다.

사이의 유일한 차이점은mv old new그리고.git mv old new은 게그바로입니다.git mv또한 파일을 인덱스에 추가합니다.

mv old new그리고나서git add -A효과도 있었을 겁니다

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

자세한 내용은 "git add -A"와 "git add" 차이점을 참조하십시오.

Git 1.7.x의 경우 다음 명령이 작동했습니다.

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

할 필요가 없었습니다.git add원본 파일(즉, css/mobile.dll)이 이미 커밋된 파일에 있었기 때문입니다.

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

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 statusbbb를 보여줍니다. 파일로 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 구현에 밑줄을 그은 경우 두 명령을 개별적으로 처리할 수 있습니다.

이야기의 교훈:파일 이름이 바뀌었는지 확실하지 않으면 "git commit --dry-run -a"를 실행합니다.파일 이름이 변경된 것으로 표시되면 바로 가셔도 됩니다.

1단계: 파일 이름을 이전 파일에서 새 파일로 변경합니다.

git mv #oldfile #newfile

2단계:git commit 댓글 추가하기 글 추 가

git commit -m "rename oldfile to newfile"

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

git push origin #localbranch:#remotebranch

당신은 해야 합니다.git add css/mobile.css과 새파및일git rm css/iphone.css그래서 Git는 그것에 대해 알고 있습니다.그러면 에 동일한 출력이 표시됩니다.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 관점에서 당신의 파일에 대해 생각해 보겠습니다.

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

(다른 것들 중에서) 리포지토리가 있습니다.

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

그리고 그것은 Git의 통제하에 있습니다.

$ 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

Git의 관점에서 보면,

  • iphone.dll이 없습니다. (삭제되었습니다. 경고합니다.)
  • 파일 mobile.dll이 있습니다.
  • 그 파일들은 전혀 관련이 없습니다.

따라서 Git는 이미 알고 있는 파일(iphone.css)과 탐지하는 새 파일(mobile.css)에 대해 조언하지만 파일이 인덱스나 HEAD에 있을 때만 Git가 내용을 확인하기 시작합니다.

현재 "iphone.css deletion" 또는 mobile.css는 인덱스에 없습니다.

iphone.css 삭제를 인덱스에 추가합니다.

$ git rm iphone.css

Git는 무슨 일이 일어났는지 정확히 알려줍니다(iphone.css는 삭제됨).더 이상 아무 일도 일어나지 않았습니다):

그런 다음 새 파일 mobile.css를 추가합니다.

$ git add mobile.css

이번에는 삭제 파일과 새 파일이 모두 인덱스에 있습니다.이제 Git는 컨텍스트가 동일함을 감지하고 이름 변경으로 노출합니다.실제로 파일이 50% 유사한 경우 작업을 이름 변경으로 유지하면서 mobile.css를 약간 변경할 수 있는 이름 변경으로 인식됩니다.

과 같은 할 수 있습니다.git diff이 인덱스에 이제파인있사합니다야용해로를 사용해야 .--cachedmobile.css를 조금 편집하여 인덱스에 추가하고 다음과 같은 차이점을 확인합니다.

$ git diff --cached

그리고.

$ git diff --cached -M

-M의 "이름 바꾸기" 옵션입니다.git diff.-M의 약자-M50%(의 유사성으로 , 를 (50% 이유인로가이해표변름현됨경로으다있니습수줄상하로)로 수 -M20%mobile.dll 파일을 많이 편집하면 (20%).

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

거기서 잘못을 저질렀군요.

당신이 파일을 추가한 후에야 Git는 내용에서 파일을 인식할 수 있습니다.

파인더 이동 결과를 준비하지 않았습니다.파인더를 통해 이동한 다음에 이동한 경우git add css/mobile.css ; git rm css/iphone.cssGit는 새 파일의 해시를 계산한 다음 파일의 해시가 일치함을 인식합니다(따라서 이름 변경).

수동으로 파일 이름을 변경해야 하는 경우(예: 스크립트를 사용하여 파일 집합의 이름을 일괄 변경한 다음git add -A .저를 위해 일했습니다.

Xcode 사용자의 경우:Xcode에서 파일 이름을 변경하는 경우 추가할 배지 아이콘이 변경됩니다.Xcode를 사용하여 커밋을 수행하면 실제로 새 파일이 생성되고 기록이 손실됩니다.

해결 방법은 간단하지만 Xcode를 사용하기 전에 먼저 해결해야 합니다.

  1. 폴더에서 Git 상태를 수행합니다.준비된 변경 내용이 올바른지 확인해야 합니다.

    renamed:    Project/OldName.h -> Project/NewName.h
    renamed:    Project/OldName.m -> Project/NewName.m
    
  2. commit -m 'name change'

    그런 다음 Xcode로 돌아가면 배지가 A에서 M으로 변경된 것을 볼 수 있으며 Xcode를 사용할 때 향후 변경 사항을 적용하기 위해 저장됩니다.

이 했습니다. 했는데 파일을 업데이트하지. 파일을 업데이트하고 싶지 않은 경우git mv효과가 있습니다: 든모것효있습가니다과이이있다▁all습니이:▁works.

  1. 을 상위디변위에서 변경/dir/RenamedFile.js/whatever/RenamedFile.js.
  2. git add -A그 변화를 준비하기 위해
  3. 을 다시 "" " " " " " " 로 변경합니다./dir/RenamedFile.js.
  4. git add -A다시, 이 변경 사항과 해당 변경 사항을 비교하여, Git가 파일 이름 변경 사항을 선택하도록 강제합니다.

Window 10에서 git 2.33으로 테스트됨

  1. 탐색기에서 필요한 폴더 및 파일의 이름을 변경합니다.
  2. git add .
  3. git commit -m "commit message"
  4. git push

Git가 이름 변경을 감지할 것입니다.실하여확인수다있니습을 실행하여 할 수 .git status 후 (커밋후후)▁comm)

여기에 이미지 설명 입력

폴더와 파일을 대문자로 표시할 때 Node.js의 파일 시스템을 사용하여 이 문제를 해결했습니다.

시작하기 전에 약속하는 것을 잊지 마세요.얼마나 안정적인지 잘 모르겠어요 :)

  1. 프로젝트 루트에 스크립트 파일을 만듭니다.
// File rename.js

const fs = require('fs').promises;
const util = require('util');
const exec = util.promisify(require('child_process').exec);

const args = process.argv.slice(2);
const path = args[0];

const isCapitalized = (s) => s.charAt(0) === s.charAt(0).toUpperCase();

const capitalize = (s) => s.charAt(0).toUpperCase() + s.slice(1);

async function rename(p) {
  const files = await fs.readdir(p, { withFileTypes: true });
  files.forEach(async (file) => {
    const { name } = file;
    const newName = capitalize(name);
    const oldPath = `${p}/${name}`;
    const dumbPath = `${p}/dumb`;
    const newPath = `${p}/${newName}`;
    if (!isCapitalized(name) && name !== 'i18n' && name !== 'README.md') {
      // 'git mv' won't work if we only changed size of letters.
      // That's why we need to rename to dumb name first, then back to current.
      await exec(`git mv ${oldPath} ${dumbPath}`);
      await exec(`git mv ${dumbPath} ${newPath}`);
    }
    if (file.isDirectory()) {
      rename(newPath);
    }
  });
}

rename(path);

디렉터리(또는 단일 파일) 스크립트의 모든 파일 이름을 변경하는 것이 더 간단합니다.

// rename.js

const fs = require('fs').promises;
const util = require('util');
const exec = util.promisify(require('child_process').exec);
const args = process.argv.slice(2);
const path = args[0];

async function rename(p) {
  const files = await fs.readdir(p, { withFileTypes: true });
  files.forEach(async (file) => {
    const { name } = file;
    const currentPath = `${p}/${name}`;
    const dumbPapth = `${p}/dumb`;
    await exec(`git mv ${currentPath} ${dumbPath}`);
    await exec(`git mv ${dumbPath} ${currentPath}`);
    if (file.isDirectory()) {
      rename(newPath);
    }
  });
}

rename(path);
  1. 인수를 사용하여 스크립트 실행
node rename.js ./frontend/apollo/queries

Node.js를 사용하여 셸 스크립트 파일 또는 명령을 실행하는 방법

언급URL : https://stackoverflow.com/questions/2641146/handling-file-renames-in-git