git local repo에서 파일을 제거하고 파일을 제자리에두고 향후 삭제로부터 파일을 보호합니다.

예술적 로봇

이것은 로컬 파일 시스템에서 파일을 삭제하지 않고 Git 저장소에서 파일제거 하기위한 후속 질문입니다.

1 단계

mkdir ~/repo
cd ~/repo
git init .
echo important >file
git add .
git commit -m "initial commit"

cd ~
git clone repo repo2
cd ~/repo2
echo really important>file

이제 하나의 파일이있는 git 저장소와 해당 저장소의 복제본이 있습니다.

이제 file1이 git에 의해 추적되는 것을 원하지 않는다고 가정 해 보겠습니다.

2 단계

$ cd ~/repo
$ git rm --cached file
$ git commit -m "remove file from repo"
$ cat file
important
$ # ↑ yes, file is still here, good

좋아, 지금까지 좋다. 파일이 저장소에서 삭제되었습니다.

다른 저장소에서 파일을 변경했을 수 있습니다.

3 단계

$ cd ../repo2
$ echo "really important">file
$ git pull
$ cat file
✖ cat: file: No such file or directory

도! 이제 파일이 삭제되었습니다.

그 이유는 git이 커밋에서 삭제를 기록하고, 해당 변경 사항을 병합 할 때 rm file파일을 잃어 버리는 것을 의미 합니다.

어쨌든 git에게 파일 (또는 dir) 추적을 중지하고 삭제를 재생하지 않도록 지시하는 것이 있습니까? 강제 업데이트없이이 작업을 수행하는 방법을 찾고 있습니다 (예 : 기록을 편집하기 위해 필터를 사용하지 않고)?

질문을 표현하는 또 다른 방법은 다음과 같습니다. 3 단계 대신 2 단계 후

$ cd ../repo2/
$ echo "really important" >file
$ echo file >.gitignore
$ git status -s
 M file
?? .gitignore

그래서이 시점 file에서은 gitignore에 있지만 git은 그것을 무시하지 않습니다. 여기에 그것을 떨어 뜨리는 방법이 있습니까?

나는 유효한 대답이 "아니오, 그건 말도 안 돼서 자식이 작동하는 모든 방식을 완전히 깨뜨릴 것이다"라는 것을 알고 있지만, 나는이 상황에서 몇 번 찔려서 물어볼 것이라고 생각했다.

화요일

어쨌든 git에게 파일 (또는 dir) 추적을 중지하고 삭제를 재생하지 않도록 지시 할 수 있습니까?

호 그러나 그것을 얻을 수있는 방법도 없다 "삭제를 재생는". Git은 실제로 아무것도 재생 하지 않습니다 . "재생"이라는 개념은 실제로 일어나는 일의 축약 형입니다.

... 그래서이 시점 file에서 gitignore에 있지만 git은 그것을 무시하지 않습니다. 여기에 그것을 떨어 뜨리는 방법이 있습니까?

아니.

실제 그림은 플라톤의 동굴 에서 그림자를 가지고 노는 다른 모든 시도는 다음과 같습니다.

  • Git은 커밋을 저장 합니다. 저장소 파일 (및 메타 데이터)을 커밋하지만 저장 단위는 커밋입니다. (참고 : 커밋은 디렉토리 / 폴더가 아니라 파일 만 저장합니다. 파일 이름에 슬래시가 포함될 수 있습니다. foo/bar/baz.ext은 이름이 긴 파일입니다.)

  • 커밋의 "실제 이름"은 해시 ID입니다.

  • 커밋의 어떤 부분도 변경할 수 없습니다. 항목을 만들 수 있지만 기존 항목은 변경할 수 없습니다. 완전히 읽기 전용입니다. 그 안에있는 파일은 특수 압축 된 읽기 전용 Git 전용 형식입니다. 나는 그것들 을 재수화할 때까지 사용할 수 없기 때문에 동결 건조 라고 부르는 것을 좋아 합니다.

  • 따라서 커밋에 대해 작업 할 수 없으며 작업하지도 않습니다. 따라서 Git은 작업 수행 있는 영역을 제공합니다. Git은 작업 트리 , 작업 트리 또는 작업 디렉토리 또는 여러 유사한 이름을 호출합니다 . 저는 하이픈으로 연결된 작업 트리를 사용하는 경향이 있습니다.

    작업 트리의 파일은 읽기 / 쓰기입니다. 그것들은 평범한 일상 파일입니다. 파일 시스템 dir/file.ext에서 Git 이라는 파일을 저장할 디렉토리 / 폴더를 만들도록 요구하는 경우 Git은 그 때 디렉토리를 만듭니다.

    Git 체크 아웃 한 일부 커밋을 기반으로 작업 트리를 채우지 만 추가 단계가 있습니다. 체크 아웃 한 커밋은 무엇이든 (해시 ID로 식별되고 분기 이름으로 자주 발견되는 해시 ID로 식별 됨) 파일을 제공합니다. 그 커밋이 무엇이든 현재 커밋입니다. 이름 HEAD은이 현재 커밋을 참조합니다 (분기 이름으로 선택한 경우 분기 이름도 참조).

  • 앉아 사이에 현재는 커밋하는 기억, 읽기 전용-하고 작업 트리, 힘내 힘내는 호출하는 데이터 구조를 협지 인덱스 , 또는 준비 영역 , 또는 - 드물게 이러한 일 - 더 캐시를 . 이들은 동일한 엔티티에 대한 세 가지 이름입니다. 이름 색인 은 의미가 없지만 여기서 사용할 것입니다. (다른 두 이름은 파일을 "스테이징"하는 데 사용하는 방법과 캐시를 통해 작업 속도를 높이기 위해 Git에서 사용하는 방법에 대해 더 암시 적입니다.)

여기에있는 거의 모든 문제는 색인과 관련이 있으므로 좀 더 자세히 살펴 보겠습니다. 충돌하는 병합 중에 더 큰 역할을하지만, 대부분의 경우 인덱스에 대해 알아야 할 사항 (사용 방식)은 다음 커밋 에 저장할 파일을 나타내는 것 입니다.

먼저 체크 아웃 할 때 일부는 작업 트리의 모든에서 진정한 빈 인덱스없이 파일을 새로 복제 된 저장소에 커밋 기존 망할 놈의 첫 번째 사본을 모두 선택한에서 파일을 커밋 인덱스. 1 색인 사본 (참조, 각주 1 참조)은 특수 동결 건조 형식입니다. 커밋 된 사본과 달리하지만, 당신은 수있는 새로운 파일을 덮어 씁니다.

색인을 채운 Git은 이제 모든 색인 사본을 재수 화하고 현재 일상적인 형식의 파일을 작업 트리에 배치하여 작업 트리를 채 웁니다 (필요한 경우 폴더 생성).

따라서이 시점에서 모든 파일에는 읽기 전용 HEAD복사본, 즉 읽기 전용 복사본이 있습니다. 덮어 쓸 수있는 고정 형식 인덱스 복사본 그리고 실제로 사용할 수있는 일반 형식의 일반 파일 사본. "추적 됨"은 "색인에 있음"을 의미하기 때문에 이러한 파일은 추적 됩니다.

작업 트리 사본에서 복사하여 이전에 존재하지 않았던 새 파일을 색인에 추가 할 수 있습니다.

echo new file > newfile.ext
git add newfile.ext

색인 작업 트리 모두 에서 기존 파일을 제거 할 수 있습니다 .

git rm oldfile

또는 색인에서 파일을 제거하고 작업 트리에 사본을 남겨 둘 수 있습니다.

git rm --cached oldfile

아마도 새 버전과 향상된 버전으로 기존 파일을 덮어 쓸 수 있습니다.

# fix up existingfile.py
git add existingfile.py

색인에서 변경 한 모든 내용은 제안 된 다음 커밋을 나타냅니다 . 이 시점에서 새 파일 하나를 추가하고 기존 파일 하나를 제거하고 기존 파일 하나를 업데이트했습니다. 이제 실행하면 :

git commit

Git은 지금 인덱스에있는 모든 것으로 부터 새로운 커밋을 빌드 할 것 입니다. 새 커밋에는 다음을 제외하고 이전 커밋의 모든 파일이 있습니다 .

  • 더 이상 가지고 있지 않습니다 oldfile.
  • 그것은 지금 가지고 있습니다 newfile.ext;
  • 다른 버전의 existingfile.py.

당신이 갈 경우 이 새로운 이전과 새로운 스냅 샷을 모두 추출, 임시 영역에서 귀하에게, 힘내 쇼 커밋 한 다음 비교. 2 동일한 모든 파일에 대해 Git은 아무 말도하지 않습니다. 사라진 파일 ( oldfile)의 경우 Git은 파일이 "삭제"되었다고 주장합니다. 새 파일의 경우 Git은 해당 파일이 추가되었다고 주장하고, 둘 다에 있지만 다른 파일의 경우 Git은 이전 콘텐츠를 새 콘텐츠로 변경할 수있는 일련의 지침을 생성합니다.

새 커밋은 브랜치의 팁 커밋이되고 (Git는 브랜치 이름에 새 해시 ID를 저장함) HEAD이제 방금 만든 새 커밋을 참조합니다.


1 기술적으로 색인은 파일의 사본이 아닌 파일에 대한 참조보유 합니다. 그러나 git update-index직접 사용을 시작 하거나 사용되는 공간을 검사 하지 않는 한 여기서 차이점을 구분할 수 없습니다. 색인이 사본을 보유한 것처럼 생각하는 것이 더 쉽습니다.

2 내부 저장소 형식으로 인해 Git은 변경되지 않은 모든 파일의 추출을 즉시 건너 뛸 수 있습니다. 나머지는 디스크가 아닌 메모리에서 발생합니다.


지금까지이 모든 것이 말이되는데 무엇이 잘못 되었습니까?

위의 모든 사항을 감안할 때 git rm --cached를 제거 하는 데 사용 oldfile했으므로 작업 트리에 여전히 남아 있다고 가정 합니다.

자, 어떤 이유-호기심에 대한 필요가 - 우리가되는 힘내 직접 어떤 오래된 버그 수정 세 이상 이 커밋 않습니다 있습니다 .git checkoutoldfile

Git은 .NET을 포함하여 해당 커밋의 모든 파일에서 색인을 충실하게 채 웁니다 oldfile. 그래서 oldfile지금 추적 됩니다. Git은의 오래된 내용을 oldfile작업 트리로 추출합니다 . 3 우리는 우리가하는 것은, (지점의 끝에서 이제 하나) 최신 커밋 우리로 돌아가 다음 커밋 이전으로 할 필요가 있고, 무엇이든 할 수 oldfile 없는 커밋에.

Git oldfile은 추적 (인덱스에 있음)을 확인했지만 원하는 커밋에 존재 하지 않으므로 원하는 커밋 + 분기를 체크 아웃 할 oldfile때 인덱스 와 작업 트리에서 제거합니다 . 이제 파일이 작업 트리에 더 이상 표시되지 않습니다. 이 점에 유의 힘내에서 파일의 복사본입니다 이전 커밋에서. 예를 들어를 사용하여 이전 커밋에서 내용을 추출 할 수 있습니다 .git show commit:path


3 힘내 그러나 먼저 확인이 우리의 덮어 쓰기 여부를 현재 의 사본을 oldfile. 그렇다면 Git은 사용자가 --force또는 다양한 다른 옵션 을 사용하지 않는 한 파일을 덮어 쓰겠다고 체크 아웃을 거부합니다 . 참고 : 에 파일을 추가하면 .gitignore이에 부정적인 영향 미칩니다. 가끔 Git은 파일을 자유롭게 방해 할 것입니다!


.gitignore

파일을 추적하면 파일을 나열 해도 효과.gitignore없습니다 .

파일이 추적 되지 않은 경우 (인덱스에없는 경우) Git은 일반적으로 추적 되지 않은 파일이 있음을 알려줍니다. 에 파일을 나열하여 Git을 종료 할 수 있습니다 .gitignore. 힘내 자동으로되지 않습니다 추가 해당 파일을 이 시점에서 인덱스 : git add *또는 git add .무시 된 (여전히 비 추적) 파일을 건너 뜁니다.

정의에 따라 추적되지 않은 파일은 인덱스가 아닌 작업 트리에만 존재하므로 다음 커밋에는 파일이 없습니다.

--assume-unchanged 및 --skip-worktree

파일이 인덱스에 존재하는 경우가 있습니다 추적. 그러나 .gitignore인덱스 항목에서 변경되지 않은 가정 또는 작업 트리 건너 뛰기 플래그를 설정 하는 것과 유사한 효과를 얻을 수 있습니다 . 이것은 Git에게 알려줍니다. 파일의 인덱스 복사본을 파일의 작업 트리 복사본과 비교할 때 대부분 일치한다고 가정해야합니다.

즉, 지금 파일의 작업 트리 복사본을 수정하면 git status언급하지 않습니다. 당신이 실행하는 경우 git add ., git add이 수정되지 생각하고, 인덱스 복사를 덮어 쓰지 않습니다. (인덱스 사본을 덮어 쓰려면 파일의 내용을 압축 / 고정 건조해야하는데, 파일이 변경되지 않고 덮어 쓰지 않는다는 것을 인식하는 것에 비해 상대적으로 느립니다.)

따라서 Git을 전략적 위치에두면 작업 트리의 로컬 변경 사항과 함께 파일을 이동할 수 있습니다. 그러나 인덱스 복사본이 있기 때문에 Git이 다른 이유로 인해 인덱스 복사본 변경하거나 제거 해야하는 경우 ( 예 : 다른 버전의 파일이 있거나 파일이없는 커밋으로 전환하는 경우) Git은 파일의 색인 및 작업 트리 사본을 모두 업데이트하십시오.

그렇다면 해결책은 무엇입니까?

이 질문에 대한 진정한 답은 단일 솔루션이 없다는 것입니다. 가장 좋은 방법은 일반적으로 파일을 전혀 커밋하지 않는 것입니다. 그러나 파일을 커밋 한 경우 (기존 커밋 세트에 존재하는 경우) 단순히 처리해야합니다.

당신은 할 수 있는 모든에있는 파일이없는 향상된 새로운 앤 커밋에 일부 또는 커밋을 모두 복사 한 다음 이전 커밋 사용을 중지하고 오직 새로운 커밋을 사용합니다. 이것이 바로 git filter-branch, The BFG, 그리고 새로운 git filter-repo것입니다.

아니면 그냥 다룰 수 있습니다 . 파일 있는 커밋을 체크 아웃 하고 파일을 인덱스와 작업 트리에 복사 한다는 것을 기억하십시오 . 그러한 커밋 에서 파일 이없는 커밋으로 이동 하면 인덱스 및 작업 트리에서 파일이 제거됩니다. 당신은 어느 쪽도 노력하지 않고 제거-등의 정보 및 구성 등해야 할 파일의 소중한 데이터가있는 경우 이름을 변경 커밋 결코 새로운 이름으로 파일을, 그래서 것을 이름은 결코 저장소에 바람이 없다.

이 기사는 인터넷에서 수집됩니다. 재 인쇄 할 때 출처를 알려주십시오.

침해가 발생한 경우 연락 주시기 바랍니다[email protected] 삭제

에서 수정
0

몇 마디 만하겠습니다

0리뷰
로그인참여 후 검토

관련 기사

Related 관련 기사

뜨겁다태그

보관