저는 버전 관리가 처음이고 "커밋"이 기본적으로 작업중인 새 '현재'버전을 업데이트하는 동안 백업을 생성한다는 것을 이해합니다.
내가 이해하지 못하는 것은 실제적인 관점에서 스테이징이 무엇인지입니다. 이름으로 만 존재하는 것을 준비하는 것입니까, 아니면 목적에 부합합니까? 커밋하면 어쨌든 모든 것을 커밋 할 것입니다.
편집 : 용어를 혼동 할 수 있다고 생각합니다. '스테이지'파일은 '추적'파일과 동일한가요?
저는 버전 관리가 처음이고 "커밋"이 기본적으로 작업중인 새 '현재'버전을 업데이트하는 동안 백업을 생성한다는 것을 이해합니다.
내가 이해하지 못하는 것은 실제적인 관점에서 스테이징이 무엇인지입니다. 이름으로 만 존재하는 것을 준비하는 것입니까, 아니면 목적에 부합합니까? 커밋하면 어쨌든 모든 것을 커밋 할 것입니다.
편집 : 용어를 혼동 할 수 있다고 생각합니다. '스테이지'파일은 '추적'파일과 동일한가요?
답변:
커밋하면 인덱스 ( "스테이징 된"파일)의 변경 사항 만 커밋됩니다. 이것에 대한 많은 용도가 있지만 가장 분명한 것은 작업 변경 사항을 작은 독립된 조각으로 나누는 것입니다. 기능을 구현하는 동안 버그를 수정했을 수 있습니다. git add해당 파일 만 (또는 파일의 git add -p일부만 추가 할 수 있습니다 !) 다른 모든 것을 커밋하기 전에 해당 버그 수정을 커밋 할 수 있습니다. 사용하는 경우 커밋 직전에 모든 것을 git commit -a강제하는 것 add입니다. -a스테이징 파일을 활용 하려면 사용하지 마십시오 .
--cachedto many 명령을 사용하여 준비된 파일을 중간 작업 복사본으로 취급 할 수도 있습니다 . 예를 git diff --cached들어은 스테이지가 어떻게 다른지 보여 주므로 HEAD다른 작업 변경 사항을 혼합하지 않고도 커밋하려는 내용을 확인할 수 있습니다.
git reset --hard.
git diff --staged변경 한 파일과 위치를 확인하고 다른 변경을 시작하십시오.스테이징의 실용적인 목적 중 하나는 파일 커밋의 논리적 분리입니다.
스테이징을 통해 파일 / 작업 디렉토리를 계속 편집하고 준비가되었다고 생각할 때 부분적으로 커밋을 수행 할 수 있으므로 논리적으로 관련이없는 편집을 위해 별도의 단계를 사용할 수 있습니다.
당신이 4 개 파일이 있다고 가정 fileA.html, fileB.html, fileC.html와 fileD.html. 4 개의 파일을 모두 변경하고 커밋 할 준비가되었지만 변경 사항 은 논리적으로 관련 되어 fileA.html있으며 fileB.html(예 : 두 파일에서 동일한 새 기능 구현), 변경 사항은 이전 파일 fileC.html과 fileD.html는 별개이며 논리적으로 관련이 없습니다. 먼저 파일 fileA.html을 준비 fileB.html하고 커밋 할 수 있습니다 .
git add fileA.html
git add fileB.html
git commit -m "Implemented new feature XYZ"
그런 다음 다음 단계에서 나머지 두 파일에 대한 변경 사항을 준비하고 커밋합니다.
git add fileC.html
git add fileD.html
git commit -m "Implemented another feature EFG"
git commit -m "Implemented new feature XYZ" fileA.html fileB.html git add 명령 없이도 잘 작동합니다. 준비는 개념이 아니다 어디 그래서, 내가 자식 준비 유용성에 대해 확신 아니에요, 전복 세계에서 온
자식 명령의 사용을 이해하는 것이 더 쉽습니다 add그리고 commit당신이 상상하는 경우 로그 파일은 Github에서의 저장소에 유지되고. 일반적인 프로젝트의 로그 파일은 다음과 같습니다.
---------------- Day 1 --------------------
Message: Complete Task A
Index of files changed: File1, File2
Message: Complete Task B
Index of files changed: File2, File3
-------------------------------------------
---------------- Day 2 --------------------
Message: Correct typos
Index of files changed: File3, File1
-------------------------------------------
...
...
...and so on
나는 보통 하루를 git pull요청 으로 시작하고 요청으로 끝 git push냅니다. 따라서 하루 기록의 모든 것은 그들 사이에서 일어나는 일과 일치합니다. 매일 몇 개의 파일을 변경해야하는 하나 이상의 논리적 작업 이 있습니다. 해당 작업 중에 편집 된 파일은 색인에 나열됩니다.
이러한 각 하위 작업 (여기서 작업 A 및 작업 B)은 개별 커밋입니다. 이 git add명령은 '변경된 파일 색인'목록에 파일을 추가합니다. 이 프로세스를 스테이징이라고도합니다. 그만큼git commit 명령은 사용자 지정 메시지와 함께 변경 사항 및 해당 색인 목록을 기록 / 마무리합니다.
여전히 저장소의 로컬 복사본 만 변경하고 Github의 복사본은 변경하지 않습니다. 그런 다음 'git push'를 수행 할 때만 기록 된 모든 변경 사항을 각 커밋에 대한 인덱스 파일과 함께 수행하고 기본 저장소 (Github)에 기록됩니다.
예를 들어 가상 로그 파일에서 두 번째 항목을 얻으려면 다음을 수행해야합니다.
git pull
# Make changes to these files
git add File3 File4
# Verify changes, run tests etc..
git commit -m 'Correct typos'
git push
간단히 말해서, git add그리고 git commit당신이 체계적인 논리적 하위의 변화로 주요 저장소에 대한 변경을 분해 할 수 있습니다. 다른 답변과 의견이 지적했듯이 당연히 더 많은 용도가 있습니다. 그러나 이것은 가장 일반적인 사용 중 하나이며 Svn과 같은 다른 인기있는 시스템과 달리 Git의 다단계 개정 제어 시스템의 기본 원리입니다.
Ben Jackson의 대답 을 확장하기 위해 원래 질문을 자세히 살펴 보겠습니다. ( 왜 유형 질문을 괴롭히는 지에 대한 답변을 참조하십시오 . 이것은 진행 상황에 대한 자세한 내용 입니다 .)
저는 버전 관리가 처음이고 "커밋"이 기본적으로 작업중인 새 '현재'버전을 업데이트하는 동안 백업을 생성한다는 것을 이해합니다.
이것은 아니다 아주 좋아. 백업 및 버전 제어는 확실히 관련이 있습니다. 정확히 어느 정도는 의견의 문제가되는 몇 가지 사항에 얼마나 크게 의존하지만 의도적으로 만 차이가있을 수 있습니다. 백업은 일반적으로 재해 복구 (시스템 장애, 화재 파괴)를 위해 설계되었습니다. 모든 저장 매체 등을 포함한 전체 건물). 버전 제어는 일반적으로 세분화 된 상호 작용을 위해 설계되었으며 백업이 제공하지 않는 기능을 제공합니다. 백업은 일반적으로 일정 시간 동안 저장되었다가 "너무 오래됨"으로 분류됩니다. 더 새로운 백업이 중요합니다. 버전 제어는 일반적으로 커밋 된 모든 버전을 영원히 저장합니다.
내가 이해하지 못하는 것은 실제적인 관점에서 스테이징이 무엇인지입니다. 이름으로 만 존재하는 것을 준비하는 것입니까, 아니면 목적에 부합합니까? 커밋하면 어쨌든 모든 것을 커밋 할 것입니다.
예, 아니오. 여기서 Git의 디자인은 다소 독특합니다. 별도의 준비 단계가 필요 하지 않은 버전 제어 시스템이 있습니다 . 예를 들어 사용 측면에서 Git과 매우 유사한 Mercurial 은 완전히 새로운 파일을 도입하는 첫 번째 단계를 넘어 별도의 단계가 필요 하지 않습니다hg add . Mercurial에서는 hg일부 커밋을 선택 하는 명령을 사용하고 작업을 수행 한 다음를 실행 hg commit하면 완료됩니다. Git을 사용하면 git checkout, 1 을 사용 하고 작업을 수행 한 다음을 실행 git add한 다음 git commit. 추가 git add단계가 필요한 이유는 무엇 입니까?
여기서 비밀은 Git이 다양한 방식으로 색인 또는 스테이징 영역 이라고 부르는 것 , 또는 가끔은 드물게 요즘에는 캐시 입니다. 이것들은 모두 같은 이름입니다.
편집 : 용어를 혼동 할 수 있다고 생각합니다. '스테이지'파일은 '추적'파일과 동일한가요?
아니요,하지만 관련이 있습니다. 추적 파일이 망할 놈의 인덱스에 존재 하나입니다. 인덱스를 제대로 이해하려면 커밋을 이해하는 것부터 시작하는 것이 좋습니다.
망할 놈의 버전 2.23 때문에, 당신은 사용할 수 있습니다 git switch대신 git checkout. 이 특별한 경우에이 두 명령은 정확히 동일한 작업을 수행합니다. 새로운 명령 git checkout은 너무 많은 것들로 가득 차 있기 때문에 존재합니다 . Git을 더 쉽고 안전하게 사용할 수 있도록 두 개의 개별 명령 git switch및 으로 분리되었습니다 git restore.
Git에서 커밋은 Git이 알고있는 모든 파일 의 전체 스냅 샷을 저장합니다 . (Git은 어떤 파일에 대해 알고 있습니까? 다음 섹션에서 확인할 수 있습니다.) 이러한 스냅 샷은 일반적으로 Git 자체 만 읽을 수있는 특수, 읽기 전용, Git 전용, 압축 및 중복 제거 된 형식으로 저장됩니다. . (가 각각 더 많은 물건은보다 커밋의 단지 이 스냅 샷,하지만 우리가 여기서 다룰 것 전부입니다.)
중복 제거는 공간 절약에 도움이됩니다. 일반적으로 몇 개의 파일 만 변경 한 다음 새 커밋을 수행합니다. 그래서 대부분의 A의 파일의 커밋 이전의 파일이 커밋 대부분 동일합니다. 이러한 파일을 직접 재사용하기 만하면 Git은 많은 공간을 절약합니다. 하나의 파일 만 건 드리면 새 커밋은 새 복사본 하나를 위한 공간 만 차지합니다 . 그런 다음에도 압축 (때로는 매우 압축되지만 실제로는 나중에 발생 함)되므로 .git디렉토리는 실제로 포함 된 파일보다 작을 수 있습니다. 커밋 된 파일은 항상 고정되므로 중복 제거는 안전 합니다. 아무도 변경할 수 없으므로 커밋이 서로의 사본에 의존하는 것이 안전합니다.
저장된 파일은이 특별한, 항상 고정 된 Git 전용 형식이기 때문에 Git은 각 파일을 일상적인 복사본으로 확장해야합니다 . 이 일반 복사본은 Git의 복사본이 아닙니다 . 원하는 대로 할 수있는 복사본입니다. Git은 당신이 그렇게하도록 지시 할 때 이것들에 쓸 것입니다. 그래서 당신이 작업 할 복사본을 갖게됩니다. 이러한 사용 가능한 사본은 작업 트리 또는 작업 트리에 있습니다. 있습니다.
이것이 의미하는 바는 특정 커밋을 체크 아웃하면 자동으로 각 파일의 두 복사본이 있다는 것입니다.
Git에는 현재 커밋 에 항상 고정 된 Git 형식의 복사본 이 있습니다. 이 복사본을 변경할 수 없습니다 (물론 다른 커밋을 선택하거나 새 커밋을 만들 수 있음).
작업 트리에 일반 형식의 사본이 있습니다. 컴퓨터의 명령을 사용하여 원하는 모든 작업을 수행 할 수 있습니다.
다른 버전 제어 시스템 (위에서 언급 한 Mercurial 포함)은이 두 가지 사본과 함께 여기서 중지됩니다. 작업 트리 사본을 수정 한 다음 커밋하면됩니다. 힘내 ...하지 않습니다.
이 두 복사본 사이에 Git 은 모든 파일 의 세 번째 복사본 2 를 저장 합니다. 이 세 번째 사본은 고정 된 형식 이지만 커밋의 고정 된 사본과 달리 변경할 수 있습니다. 이를 변경하려면 git add.
이 git add명령은 파일의 색인 사본을 작업 트리 사본과 일치시키는 것을 의미 합니다 . 즉, Git에 다음 과 같이 말합니다. 업데이트 된 작업 트리 복사본을 압축하고 중복 제거하고 새 커밋으로 고정 할 준비를하여 인덱스에있는 고정 된 형식의 중복 제거 된 복사본을 교체합니다. 당신이 경우 하지 않습니다 사용git add 인덱스는 현재 커밋의 고정 형식 복사본을 계속 유지합니다.
당신이 실행하면 git commit, 힘내 인덱스에 무엇이든 최대 패키지 바로 그때 새로운 스냅 샷으로 사용할. 이미 고정 된 형식이고 사전 중복 제거되었으므로 Git은 많은 추가 작업을 수행 할 필요가 없습니다.
또한 추적되지 않은 파일 이 무엇인지 설명합니다 . 의 비 추적 파일은 작업 트리에 있지만 파일입니다 하지 않습니다 망할 놈의 인덱스에 지금 . 이 상태에서 파일이 어떻게 감기는지는 중요하지 않습니다. 컴퓨터의 다른 위치에서 작업 트리로 복사했을 수도 있습니다. 여기서 새로 만들었을 수도 있습니다. Git의 인덱스에 복사본 이 있었을 수도 있지만 git rm --cached. 어떤 식 으로든 여기 작업 트리에 복사본이 있지만 Git의 색인에는 복사본이 없습니다. 지금 새 커밋을하면 해당 파일 은 새 커밋에 포함 .
참고 git checkout처음에 채 웁니다 (가) 체크 아웃 커밋에서 망할 놈의 인덱스입니다. 따라서 인덱스는 커밋과 일치하기 시작합니다. Git은 또한 동일한 소스에서 작업 트리를 채 웁니다. 따라서 처음에는 세 가지 모두 일치합니다. 작업 트리와 파일을 변경하면 git add이제 색인과 작업 트리가 일치합니다. 그런 다음 실행git commit 하고 Git은 인덱스에서 새 커밋을 만들고 이제 세 가지 모두 다시 일치합니다.
Git은 인덱스에서 새로운 커밋을 만들기 때문에 다음과 같이 배치 할 수 있습니다. Git의 인덱스는 사용자가 만들 계획 인 다음 커밋을 보유합니다 . 이것은 충돌하는 병합 중에 Git의 인덱스가 수행하는 확장 된 역할을 무시하지만 지금은 무시하고 싶습니다. :-)
그게 전부입니다.하지만 여전히 꽤 복잡합니다! Git의 색인에있는 내용을 정확히 확인할 수있는 쉬운 방법이 없기 때문에 특히 까다 롭습니다. 3 그러나이 있다 꽤 유용 방식으로, 진행, 그 명령이 있는지를 알려줍니다 힘내 명령 git status.
2 기술적으로 이것은 실제로 사본 이 아닙니다 . 대신, A의 참조 망할 놈의-는 ified 파일은, 사전 드 - 중복 모든 것을. 여기에는 모드, 파일 이름, 스테이징 번호 및 Git을 빠르게 만드는 일부 캐시 데이터와 같은 더 많은 항목이 있습니다. 당신이 망할 놈의 낮은 수준의 commands-의 일부 작업에 들어갈 않는 한 git ls-files --stage그리고 git update-index특히 - 당신은 사본으로 생각할 수 있습니다.
3 이 git ls-files --stage명령은 Git의 인덱스에있는 모든 파일의 이름과 스테이징 번호를 보여 주지만 일반적으로 이것은별로 유용하지 않습니다.
git status이 git status명령은 실제로 두 개의 개별git diff 명령을 합니다 (또한 어떤 분기에 있는지 알려주는 것과 같은 다른 유용한 작업도 수행함).
첫 번째 git diff는 현재 커밋 (항상 고정되어 있음)을 Git의 인덱스에있는 것과 비교합니다. 동일한 파일의 경우 Git은 아무 말도하지 않습니다. 다른 파일의 경우 Git은이 파일이 커밋을 위해 준비 되었음을 알려줍니다 . 여기에는 완전히 새로운 파일이 포함됩니다. 커밋에는 없지만 sub.py인덱스 에는 포함 되어 sub.py있는 경우이 파일이 추가되고 커밋에 포함되었지만 포함되지 않은 제거 된 파일이 모두 포함됩니다. 더 이상 색인 (git rm , 아마도).
두 번째 git diff는 Git 색인의 모든 파일을 작업 트리의 파일과 비교합니다. 동일한 파일의 경우 Git은 아무것도 말하지 않습니다. 다른 파일의 경우 Git은이 파일이 커밋을 위해 준비되지 않았 음을 알려줍니다 . 첫 번째 diff와 달리이 특정 목록 에는 완전히 새로운 파일이 포함 되지 않습니다 . 파일 untracked이 작업 트리에 있지만 Git의 인덱스에는없는 경우 Git은 추적되지 않은 파일 목록에 파일 을 추가 합니다 . 4
결국 이러한 추적되지 않은 파일을 목록에 축적하면 해당 파일의 이름도 git status알릴 수 있지만 특별한 예외가 있습니다. 파일 이름이 파일에 나열되면 이 마지막 목록이 표시되지 않습니다. 참고 목록 추적 된 파일 하나의 망할 놈의 인덱스에서이 여기에 영향을주지 않습니다 :이 비교됩니다 있도록 파일, 인덱스이며,이에 열거 된 경우에도 최선을 다하고됩니다 . 무시 파일은 "추적되지 않은 파일"불만 만 억제합니다. 5.gitignore.gitignore.gitignore
4git status — git status -s— 의 짧은 버전을 사용할 때 추적되지 않는 파일은 분리되지 않지만 원칙은 동일합니다. 이와 같은 파일을 축적하면 git status때로는 디렉토리 이름을 인쇄하여 추적되지 않는 파일 이름을 요약 할 수 있습니다 . 전체 목록을 보려면 git status -uall또는을 사용하십시오 git status -u.
5 파일을 나열 하면 추적되지 않은 파일을 건너 뛰 거나 같은 많은 파일 작업을 대량으로 추가 할 수 있습니다. 이 부분 은 일반적으로 건너 뛰는 파일을 추가하는 데 사용할 수 있으므로 조금 더 복잡해집니다 . 일반적으로 사소한 다른 특수한 경우가 있는데, 모두 이것에 추가됩니다. 파일 이 더 적절하게 호출 되거나 똑같이 다루기 힘든 것이 될 수 있습니다 . 그러나 그것은 너무 우스꽝 스럽 습니다.git add .git add *git add --force.gitignore.git-do-not-complain-about-these-untracked-files-and-do-not-auto-add-them.gitignore
git add -u, git commit -a등여기에서 알아야 할 몇 가지 편리한 단축키가 있습니다.
git add .현재 디렉토리와 하위 디렉토리에 업데이트 된 모든 파일을 추가 합니다 . 이는를 존중 .gitignore하므로 현재 추적되지 않은 파일이에 의해 불만이 제기 git status되지 않으면 자동으로 추가되지 않습니다.
git add -u작업 트리의 모든 위치에 업데이트 된 모든 파일 을 자동으로 추가 합니다 . 6 이것은 추적 된 파일 에만 영향을줍니다 . 당신이 한 경우 참고 제거 작업 트리 사본을,이 (너무 인덱스 복사를 제거합니다 이의의 일환으로 않는 메이크업 인덱스는 작업 트리에 맞는 일을).git add
git add -Agit add .작업 트리의 최상위 수준에서 실행하는 것과 같습니다 (그러나 각주 6 참조).
이 외에도, 당신은 실행할 수 있습니다 git commit -a거의 비슷 인 7 실행하는 git add -u다음과 git commit. 즉, 이것은 Mercurial에서 편리한 것과 동일한 동작을 제공합니다.
나는 일반적으로 git commit -a패턴 에 반대합니다 . git status자주 사용 하고 출력을 자세히 살펴보고 상태가 예상 한 것과 다를 경우 그 이유를 파악하는 것이 좋습니다. 을 사용하면 git commit -a실수로 파일을 수정하고 의도하지 않은 변경 사항을 커밋하기가 너무 쉽습니다. 그러나 이것은 대부분 취향 / 의견의 문제입니다.
6 Git 버전이 Git 2.0 이전 버전 인 경우 여기에서주의하십시오. git add -u현재 디렉터리 및 하위 디렉터리에서만 작동하므로 먼저 작업 트리의 최상위 수준으로 올라 가야합니다. 이 git add -A옵션에는 비슷한 문제가 있습니다.
7 실제로 추가 인덱스를 만들고 다른 인덱스를 사용하여 커밋을 수행 하기 때문에 거의 동등 하다고 말합니다 git commit -a. 커밋이 작동 하면 수행하는 것과 동일한 효과를 얻습니다 git add -u && git commit. 커밋 이 작동 하지 않는 경우 (Git가 수행 할 수있는 여러 가지 방법 중 하나로 커밋을 건너 뛰게하면 git add나중에 파일이 처리되지 않습니다. Git가 임시 추가 인덱스를 버리고 다시 기본 인덱스를 사용하기 때문입니다.) .
여기에서 사용하면 추가 합병증이 발생합니다 git commit --only. 이 경우 Git은 세 번째 인덱스를 생성하고 특히 사전 커밋 후크를 사용하는 경우 상황이 매우 까다로워집니다. 이것은 별도의 git add작업 을 사용하는 또 다른 이유 입니다.
스테이징 영역은 더 큰 유연성으로 커밋을 작성하는 데 도움이됩니다. 제작이란 커밋을 논리 단위로 나누는 것을 의미합니다. 유지 관리가 가능한 소프트웨어를 원한다면 매우 중요합니다. 이를 달성 할 수있는 가장 확실한 방법 :
단일 작업 디렉토리에서 여러 기능 / 버그에 대해 작업하고 여전히 의미있는 커밋을 만들 수 있습니다. 우리의 모든 활동이 포함 된 단일 작업 디렉토리를 갖는 것도 매우 편리합니다. (이 작업은 변경 사항이 파일과 겹치지 않는 한 스테이징 영역없이 수행 할 수 있습니다. 또한 겹치는 지 여부를 수동으로 추적해야하는 추가 책임도 있습니다.)
여기에서 더 많은 예제를 찾을 수 있습니다. 인덱스 사용
가장 좋은 점은이 워크 플로 목록에서 장점이 그치지 않는다는 것입니다. 고유 한 워크 플로우가 발생하면 스테이징 영역이 도움이 될 것이라고 거의 확신 할 수 있습니다.
@Ben Jackson과 @Tapashee Tabassum Urmi가 언급했듯이 스테이지를 사용하여 커밋을 작게 만드는 요점을 확인하고 때로는 그 목적으로 사용하지만 주로 커밋을 더 크게 만드는 데 사용합니다! 여기 내 요점이 있습니다.
몇 가지 작은 단계가 필요한 작은 기능을 추가하고 싶다고 가정 해 보겠습니다. 작은 단계에 대해 별도의 커밋을 수행하고 타임 라인을 넘치게하는 데 아무런 의미가 없습니다. 하지만 각 단계를 저장하고 필요한 경우 돌아가고 싶습니다.
나는 단순히 작은 단계를 서로 위에 놓고 그것이 커밋 할 가치가 있다고 느낄 때 커밋합니다. 이렇게하면 타임 라인에서 불필요한 커밋을 제거하면서도 마지막 단계를 실행 취소 (체크 아웃) 할 수 있습니다.
선호도에 따라 사용할 수있는 다른 방법 (git 히스토리 단순화)이 있습니다.