사전 커밋
용어함정

커밋

gabury1

커밋은 그때까지 쌓아 둔 변경을 확정하는 일입니다. 확정한다는 말이 무엇을 가리키는지는 자리마다 다릅니다. 버전관리에서는 새 커밋 하나를 만듭니다. 데이터베이스에서는 진행 중인 트랜잭션을 확정합니다.

상세

세 자리가 공유하는 뼈대는 하나입니다. 그때까지 쌓아 둔 변경을 확정한다는 것입니다. 갈리는 자리도 하나입니다. 확정한다는 말이 무엇을 대상으로 삼느냐입니다.

버전관리에서는 확정이 새 물건을 하나 만듭니다. Git 공식 문서는 git commit 이 인덱스의 현재 내용과 변경을 설명하는 로그 메시지를 담은 새 커밋을 만든다고 적습니다. 그 새 커밋은 HEAD 의 직계 자식이 됩니다. Git 내부 문서는 그 커밋 객체가 무엇을 담는지 적어 둡니다. 그 시점 프로젝트 스냅샷의 최상위 트리, 있다면 부모 커밋들, 작성자와 커미터 정보, 빈 줄, 그리고 커밋 메시지입니다. 확정이 끝나면 이 객체가 저장소에 남습니다.

데이터베이스에서는 확정이 이미 열려 있던 것을 대상으로 삼습니다. PostgreSQL 공식 문서는 COMMIT 이 현재 트랜잭션을 커밋한다고 적습니다. 그 트랜잭션이 만든 모든 변경은 다른 쪽에 보이게 됩니다. 크래시가 일어나도 지속되는 것이 보장됩니다. 이 정의 문장이 가리키는 것은 새로 만들어지는 물건이 아니라 진행 중이던 트랜잭션입니다.

분산 트랜잭션에서는 확정이 두 번에 나뉩니다. PostgreSQL 공식 문서는 COMMIT PREPARED 가 준비 상태에 있는 트랜잭션을 커밋한다고 적습니다. 이 자리에서 커밋이라는 말은 그 두 번 중 뒷번을 가리킵니다.

그래서 커밋했다는 말만으로는 무슨 일이 벌어졌는지가 안 정해집니다. 맥락 이름을 먼저 대야 뜻이 섭니다.

맥락별 뜻

맥락 뜻 출처
버전관리 인덱스의 현재 내용을 담은 새 기록을 저장소에 남기는 일, 그리고 그렇게 남은 객체 Git Documentation, git-commit · Pro Git, Git Internals - Git Objects
데이터베이스 현재 트랜잭션을 확정해 변경을 다른 쪽에 보이게 하고 크래시에도 남게 하는 연산 PostgreSQL Documentation, COMMIT
분산 트랜잭션 준비 단계를 마친 트랜잭션을 확정하는 뒷단 명령 PostgreSQL Documentation, COMMIT PREPARED · PREPARE TRANSACTION

버전관리

Git 공식 문서는 커밋할 내용을 지정하는 방법이 여러 가지라고 적습니다. 그중 하나가 커밋 명령을 쓰기 전에 git add 로 변경을 인덱스에 조금씩 올려 두는 것입니다. 커밋은 그 인덱스의 현재 내용을 담아 새 기록을 만듭니다.

새 커밋은 HEAD 의 직계 자식이 됩니다. 문서는 HEAD 가 대개 현재 브랜치의 끝이라고 적습니다. 그리고 브랜치가 새 커밋을 가리키도록 갱신됩니다. 작업 트리에 브랜치가 붙어 있지 않으면 그 갱신은 일어나지 않습니다. 문서는 그 상태의 HEAD 를 분리됐다고 적습니다.

flowchart TD
    W["변경한 파일"] -->|git add| I["인덱스"]
    I -->|git commit| C["새 커밋"]
    P["HEAD 가 가리키던 커밋"] -->|부모| C
    C --> B["브랜치가 새 커밋을 가리킨다"]

남는 물건이 무엇인지는 Git 내부 문서가 적어 둡니다. 커밋 객체를 만들려면 트리 하나와, 있다면 그 앞에 바로 있던 커밋 객체들을 지정합니다. 커밋 객체의 형식은 최상위 트리, 있다면 부모 커밋, 작성자와 커미터 정보, 빈 줄, 커밋 메시지로 이루어집니다. 작성자 정보는 설정에 적힌 이름과 메일 주소, 그리고 시각으로 만들어집니다.

데이터베이스

PostgreSQL 공식 문서는 COMMIT 이 현재 트랜잭션을 커밋한다고 적습니다. 그 트랜잭션이 만든 모든 변경이 다른 쪽에 보이게 됩니다. 크래시가 일어나도 지속되는 것이 보장됩니다.

flowchart TD
    B["BEGIN"] --> S["SQL 명령 여러 개"]
    S --> C["COMMIT"]
    S --> R["ROLLBACK"]
    C --> V["변경이 다른 쪽에 보인다"]
    R --> D["변경이 버려진다"]

커밋을 직접 치지 않아도 커밋은 일어납니다. 문서는 PostgreSQL 이 모든 SQL(Structured Query Language) 명령을 실제로는 트랜잭션 안에서 실행되는 것으로 다룬다고 적습니다. BEGIN 을 내지 않으면 낱개 명령마다 암묵적인 BEGIN 이 붙습니다. 성공하면 COMMIT 도 함께 감싸집니다. BEGIN 과 COMMIT 으로 둘러싼 명령 묶음을 때로는 트랜잭션 블록이라고 부른다고 문서는 적습니다. 세이브포인트를 쓰면 트랜잭션의 일부만 골라 버리고 나머지는 커밋할 수 있다고도 적습니다.

트랜잭션 바깥에서 COMMIT 을 내면 해가 없다고 문서는 적습니다. 다만 경고 메시지를 부른다고 적습니다.

분산 트랜잭션

여기서는 확정이 PREPARE TRANSACTION 과 COMMIT PREPARED 두 번으로 나뉩니다. 커밋이라는 말은 그 두 번 중 뒷번만 가리킵니다. 곧 이미 준비를 마친 준비된 트랜잭션을 확정하는 쪽입니다. 준비가 무엇을 하고 그 뒤로 무엇이 달라지는지는 2단계 커밋 항목이 받습니다.

경계

커밋에 안 들어가는 것부터 긋습니다.

푸시는 커밋이 아닙니다. Git 공식 문서는 push 를 로컬 저장소에서 하나 이상의 원격 저장소에 있는 브랜치·태그·참조를 갱신하는 동작이라고 적습니다. 원격에 아직 없는 데이터를 함께 보냅니다. 커밋은 원격을 보지 않습니다.

스테이징도 커밋이 아닙니다. Git 공식 문서는 add 가 새 파일이나 바뀐 파일의 내용을 인덱스에 넣는 일이라고 적습니다. 인덱스는 스테이징 영역이라고도 불립니다. 다음 커밋의 내용을 준비하는 자리입니다. 인자 없이 커밋 명령을 실행하면 스테이징된 변경만 커밋됩니다.

데이터베이스에서 커밋은 트랜잭션 자체가 아닙니다. PostgreSQL 공식 문서는 트랜잭션을 성공적으로 끝내려면 COMMIT 을 쓰라고 적습니다. 중단하려면 ROLLBACK 을 쓰라고 적습니다. ROLLBACK 은 현재 트랜잭션을 되돌립니다. 그 트랜잭션이 만든 갱신은 모두 버려집니다. 커밋은 트랜잭션의 두 결말 중 한쪽입니다.

여기서 애매한 케이스가 하나 남습니다. 양쪽 다 되돌리는 명령을 가지고 있습니다. 그러면 되돌림이 되느냐가 두 뜻을 가르는 선입니까. 아닙니다. 두 명령이 손대는 대상이 애초에 다릅니다. Git 공식 문서는 revert 를 이렇게 적습니다. 기존 커밋 하나 이상이 주어지면 그 패치들이 들여온 변경을 되돌린다는 것입니다. 그리고 되돌린 내용을 기록하는 새 커밋들을 기록한다는 것입니다. 앞선 커밋을 지우는 것이 아닙니다. 되돌리는 내용을 담은 커밋을 새로 얹는 것입니다. 바로 앞에서 본 ROLLBACK 이 되돌리는 것은 현재 트랜잭션입니다. 아직 확정하지 않은 것이 그 대상입니다. 그래서 갈리는 것은 커밋이라는 말이 무엇을 대상으로 삼느냐입니다.

관련 항목

커밋 객체를 이루는 구성 요소

트리 · 부모 커밋 · 커밋 메시지

커밋이 낳는 결과물의 종류

커밋 객체 · 병합 커밋 · 패치

커밋의 부모와 갱신 대상을 정하는 참조

HEAD · 브랜치 · 분리된 HEAD

커밋 전에 거치는 준비 단계

인덱스 · 스테이징 영역 · 작업 트리

커밋을 대상으로 삼는 git 명령

리베이스 · 되돌리기 · 푸시

커밋이 놓이거나 저장되는 저장소

저장소 · 로컬 저장소 · 원격 저장소

커밋이 이뤄지는 단위와 방식

트랜잭션 · 트랜잭션 블록 · 세이브포인트 · 자동 커밋

커밋의 결말과 지키는 성질

롤백 · 지속성 · 가시성

커밋이 속하는 2단계 확정 절차

2단계 커밋 · 준비된 트랜잭션 · 세션 · 디스크

다른 이름: commit