git 명령어: 커밋과 브랜치 병합, 되돌리기(reset, revert)

git 명령어는 파일의 변경 이력을 저장소에 기록하고 필요할 때 되돌리는 버전 관리 도구 git을 터미널에서 다루는 명령입니다. AlmaLinux 9 서버의 빈 폴더에 새 저장소를 만들어 커밋과 브랜치 병합, 충돌 해결, 되돌리기까지 직접 실행해 보니, reset은 커밋을 기록에서 빼고 revert는 되돌리는 커밋을 새로 쌓아 두 기록이 다르게 남았습니다.
아래 출력의 사용자 이름과 이메일, 저장소 경로는 예시 값입니다. 원격 저장소에는 연결하지 않았으므로 push와 pull, clone은 git 공식 문서 기준으로 정리했습니다.
1️⃣ git 명령어 기본 흐름
git은 파일을 세 자리로 나눠 관리합니다. 파일을 직접 고치는 작업 폴더, 다음 커밋에 넣을 변경을 모아 두는 스테이징 영역, 커밋이 차례로 쌓이는 저장소입니다.
스테이징 영역은 우체국 창구에 내기 전에 이번에 보낼 물건만 골라 상자에 담아 두는 것과 같습니다.
git add는 작업 폴더의 변경을 스테이징 영역에 담고, git commit은 담긴 변경만 저장소에 기록합니다. 되돌릴 때는 반대 방향으로 git restore를 실행합니다.
$ git add hello.shgit commit -m "Change greeting"git restore --staged hello.shgit restore hello.sh자주 사용하는 git 명령어와 하는 일을 정리하면 아래 표와 같습니다.
| 명령 | 하는 일 |
|---|---|
| git init | 지금 폴더(또는 이름을 붙인 폴더)에 새 저장소를 만듦 |
| git config --local user.name | 이 저장소의 커밋 작성자 이름을 정함 |
| git status | 파일이 작업 폴더·스테이징 영역·저장소 중 어디까지 와 있는지 확인 |
| git add 파일 | 작업 폴더의 변경을 스테이징 영역에 담음 |
| git commit -m 메시지 | 스테이징 영역에 담은 변경을 커밋으로 기록 |
| git diff | 아직 담지 않은 변경을 줄 단위로 확인 |
| git log --oneline | 커밋 기록을 한 줄씩 출력 |
| git switch -c 브랜치 | 새 브랜치를 만들고 그 브랜치로 이동 |
| git merge 브랜치 | 다른 브랜치의 커밋을 지금 브랜치에 병합 |
| git restore 파일 | 작업 폴더에서 고친 내용을 버림 |
| git reset --soft HEAD~1 | 마지막 커밋만 취소하고 변경은 스테이징 영역에 남김 |
| git revert HEAD | 마지막 커밋을 되돌리는 커밋을 새로 만듦 |
| git push | 커밋을 원격 저장소로 보냄 |
2️⃣ git 저장소 만들기: init · config
새 저장소는 git init으로 만듭니다. 폴더 이름을 붙여 실행하면 그 폴더를 새로 만들고 안에 저장소를 준비합니다.
git init projecthint: Using 'master' as the name for the initial branch. This default branch name
hint: will change to "main" in Git 3.0. To configure the initial branch name
hint: to use in all of your new repositories, which will suppress this warning,
hint: call:
hint:
hint: git config --global init.defaultBranch <name>
hint:
hint: Names commonly chosen instead of 'master' are 'main', 'trunk' and
hint: 'development'. The just-created branch can be renamed via this command:
hint:
hint: git branch -m <name>
hint:
hint: Disable this message with "git config set advice.defaultBranchName false"
Initialized empty Git repository in /root/project/.git/마지막 줄의 .git 폴더가 저장소 본체이고, 위의 hint 줄은 첫 브랜치 이름이 master로 정해졌다는 안내입니다. 안내문에 Git 3.0부터 기본 이름이 main으로 바뀐다고 적혀 있어, 첫 커밋 전에 브랜치 이름을 main으로 바꿨습니다.
cd projectgit branch -m maingit statusOn branch main
No commits yet
nothing to commit (create/copy files and use "git add" to track)첫 줄에 바뀐 브랜치 이름 main이 나오고, 아직 커밋이 없어 [No commits yet]이 붙습니다.
커밋에 남을 이름과 이메일은 git config로 정합니다. --local을 붙이면 이 저장소의 .git/config 파일에만 기록되어, 같은 서버의 다른 저장소에는 영향이 없습니다.
git config --local user.name "Example User"git config --local user.email "user@example.com"git config --local --listcore.repositoryformatversion=0
core.filemode=true
core.bare=false
core.logallrefupdates=true
user.name=Example User
user.email=user@example.com목록 끝의 user.name과 user.email 두 줄이 방금 넣은 값입니다. git config 매뉴얼 기준으로 --global을 붙인 설정은 사용자 홈 폴더의 .gitconfig 파일에 기록되고, 그 계정의 모든 저장소에 적용됩니다.
3️⃣ git 커밋 명령어: add · commit
저장소를 만든 직후에는 폴더에 있던 파일도 git의 추적 대상 밖에 있습니다. README.md와 hello.sh 두 파일을 넣고 상태를 확인했습니다.
git statusOn branch main
No commits yet
Untracked files:
(use "git add <file>..." to include in what will be committed)
README.md
hello.sh
nothing added to commit but untracked files present (use "git add" to track)두 파일이 [Untracked files] 아래 나옵니다. git이 아직 한 번도 기록하지 않은 새 파일이라는 뜻입니다.
git add README.mdgit statusOn branch main
No commits yet
Changes to be committed:
(use "git rm --cached <file>..." to unstage)
new file: README.md
Untracked files:
(use "git add <file>..." to include in what will be committed)
hello.sh
README.md만 [Changes to be committed] 아래 new file로 옮겨지고, 담지 않은 hello.sh는 그대로 남습니다.
git status -sA README.md
?? hello.sh-s를 붙이면 파일마다 한 줄로 짧게 나옵니다. 앞 글자 A는 스테이징 영역에 새로 담긴 파일이고, ??는 추적하지 않는 파일입니다.
git add .git status -sA README.md
A hello.sh점(.)은 지금 폴더 아래의 변경 전부를 의미하므로, 두 파일 모두 A로 바뀝니다.
git commit -m "Add README and hello script"[main (root-commit) a869c5f] Add README and hello script
2 files changed, 2 insertions(+)
create mode 100644 README.md
create mode 100644 hello.sh첫 커밋이라 root-commit이 붙고, 이어지는 a869c5f가 이 커밋의 짧은 해시입니다. 아래 두 줄은 두 파일이 새로 만들어졌다는 기록입니다.
git statusOn branch main
nothing to commit, working tree clean커밋 뒤에는 [nothing to commit, working tree clean]이 나옵니다. 작업 폴더와 스테이징 영역, 저장소의 내용이 모두 같아졌다는 뜻입니다.
4️⃣ git 변경 내용 확인: diff · log
커밋한 뒤 파일을 고쳤다면, 무엇이 바뀌었는지 git diff로 확인합니다. hello.sh의 인사말을 Hello에서 Hello, Git으로 고친 뒤 짧은 상태부터 봤습니다.
git status -s M hello.sh앞 칸이 비고 뒤 칸에 M이 붙어, 작업 폴더에서만 고쳐진 상태입니다.
git diffdiff --git a/hello.sh b/hello.sh
index e264ff7..92b49bf 100644
--- a/hello.sh
+++ b/hello.sh
@@ -1 +1 @@
-echo Hello
+echo Hello, Git-로 시작하는 줄이 지운 내용, +로 시작하는 줄이 더한 내용입니다. @@ 줄의 -1 +1은 바뀐 줄이 고치기 전과 뒤 모두 1행에 있다는 뜻입니다.
git add로 담은 뒤에는 git diff가 아무것도 출력하지 않습니다. 담긴 변경은 --staged를 붙여 확인합니다.
git add hello.shgit diff --stageddiff --git a/hello.sh b/hello.sh
index e264ff7..92b49bf 100644
--- a/hello.sh
+++ b/hello.sh
@@ -1 +1 @@
-echo Hello
+echo Hello, Git같은 변경이 이번에는 마지막 커밋과 스테이징 영역의 차이로 나옵니다. 확인한 뒤 Change greeting이라는 메시지로 두 번째 커밋을 만들고 기록을 확인했습니다.
git commit -m "Change greeting"[main ae75c08] Change greeting
1 file changed, 1 insertion(+), 1 deletion(-)git logcommit ae75c08290885a6fb47ef89a6abd02674cb01f09 (HEAD -> main)
Author: Example User <user@example.com>
Date: Wed Oct 28 22:51:34 2026 +0000
Change greeting
commit a869c5f6cde3497e862e4a54cf35d5347aaec287
Author: Example User <user@example.com>
Date: Wed Oct 28 22:51:28 2026 +0000
Add README and hello scriptgit log는 최근 커밋부터 해시와 작성자, 시각, 메시지를 출력합니다. 맨 위 커밋 옆의 HEAD -> main은 지금 있는 main 브랜치의 마지막 커밋이 이 커밋이라는 뜻입니다.
커밋이 쌓여 화면을 넘으면 git log는 less로 열리고, q를 누르면 닫힙니다. 테스트한 서버에서 git이 사용하는 기본 페이저도 less였습니다.
git log --onelineae75c08 (HEAD -> main) Change greeting
a869c5f Add README and hello script--oneline을 붙이면 짧은 해시와 메시지만 한 줄씩 나와, 되돌릴 커밋을 고를 때 해시를 찾기 쉽습니다.
5️⃣ git 브랜치 명령어: branch, switch, merge
main 브랜치에서 바로 고치면 작업 중인 변경과 이미 완성된 코드가 한 줄기에 섞입니다. 새 기능은 브랜치를 따로 만들어 작업하고, 끝나면 main에 병합합니다.
git branch* maingit switch -c featureSwitched to a new branch 'feature'-c는 브랜치를 만들면서 바로 그 브랜치로 이동하는 옵션입니다. feature 브랜치에서 bye.sh를 추가해 커밋했습니다.
git add bye.shgit commit -m "Add bye script"[feature b2f2dce] Add bye script
1 file changed, 1 insertion(+)
create mode 100644 bye.shgit branch* feature
main별표(*)가 붙은 줄이 지금 있는 브랜치입니다.
git switch mainSwitched to branch 'main'lsREADME.md
hello.shmain으로 돌아오면 feature에서 만든 bye.sh가 작업 폴더에서 사라집니다. 브랜치를 바꾸면 작업 폴더가 그 브랜치의 마지막 커밋 내용으로 바뀝니다.
git log --oneline --graph --all* b2f2dce (feature) Add bye script
* ae75c08 (HEAD -> main) Change greeting
* a869c5f Add README and hello script--all은 모든 브랜치의 커밋을 함께 출력하고, --graph는 왼쪽에 줄기를 그립니다. feature가 main보다 커밋 하나 앞서 있습니다.
git merge featureUpdating ae75c08..b2f2dce
Fast-forward
bye.sh | 1 +
1 file changed, 1 insertion(+)
create mode 100644 bye.shmain에 따로 생긴 커밋이 없어, main을 feature의 커밋으로 옮기기만 하는 Fast-forward 병합으로 끝납니다. 병합한 브랜치는 git branch -d로 지웁니다.
git branch -d featureDeleted branch feature (was b2f2dce).두 브랜치가 같은 파일의 같은 줄을 서로 다르게 고치면, git은 병합을 멈추고 충돌(CONFLICT)을 알립니다. docs 브랜치와 main에서 README.md 둘째 줄을 각각 다르게 고쳐 커밋한 뒤 병합했습니다.
git merge docsAuto-merging README.md
CONFLICT (content): Merge conflict in README.md
Automatic merge failed; fix conflicts and then commit the result.git statusOn branch main
You have unmerged paths.
(fix conflicts and run "git commit")
(use "git merge --abort" to abort the merge)
Unmerged paths:
(use "git add <file>..." to mark resolution)
both modified: README.md
no changes added to commit (use "git add" and/or "git commit -a")cat README.md# My Project
<<<<<<< HEAD
Hello and bye scripts
=======
Shell script examples
>>>>>>> docs<<<<<<< HEAD부터 ======= 사이가 main의 내용이고, 그 아래부터 >>>>>>> docs까지가 docs 브랜치의 내용입니다. 이 구분 줄을 지우고 남길 내용으로 파일을 고친 뒤 git add로 담으면 충돌이 해결된 것으로 기록됩니다. 여기서는 두 줄을 하나로 합쳐 Hello and bye shell script examples로 고쳤습니다.
git add README.mdgit status -sM README.mdgit commit -m "Merge branch docs"[main 7027cf4] Merge branch docsgit log --oneline --graph -5* 7027cf4 (HEAD -> main) Merge branch docs
|\
| * 75613dd (docs) Describe project
* | e1ac2cb Describe scripts
|/
* b2f2dce Add bye script
* ae75c08 Change greetingdocs 쪽 커밋과 main 쪽 커밋이 갈라졌다가 병합 커밋 7027cf4에서 다시 합쳐집니다.
6️⃣ git 되돌리기 명령어: restore, reset, revert
되돌릴 대상이 작업 폴더의 변경인지, 스테이징 영역에 담은 변경인지, 이미 만든 커밋인지에 따라 명령이 다릅니다. 커밋하지 않은 변경을 버릴 때는 git restore를 실행합니다. hello.sh 끝에 echo debug 한 줄을 더한 뒤 상태를 봤습니다.
git status -s M hello.shgit restore hello.shcat hello.shecho Hello, Gitecho debug 줄이 사라지고, 마지막 커밋의 내용으로 돌아옵니다. git restore는 되묻지 않고 고친 내용을 바로 지우므로, 남길 변경이 있는지 git diff로 먼저 확인합니다.
git add로 담은 변경을 스테이징 영역에서만 뺄 때는 --staged를 붙입니다. README.md 끝에 사용법 한 줄을 더해 담은 뒤 실행했습니다.
git add README.mdgit status -sM README.mdgit restore --staged README.mdgit status -s M README.mdM이 앞 칸에서 뒤 칸으로 옮겨지고, README.md에 더한 줄은 작업 폴더에 그대로 남습니다.
이미 만든 커밋은 git reset으로 취소합니다. --soft는 커밋만 취소하고 그 변경은 스테이징 영역에 남깁니다.
git add README.mdgit commit -m "Add usage"[main 6450f2d] Add usage
1 file changed, 1 insertion(+)git reset --soft HEAD~1git status -sM README.mdHEAD~1은 지금 커밋의 바로 앞 커밋입니다. Add usage 커밋이 사라지고 README.md는 스테이징 영역에 담긴 상태로 돌아와, 메시지를 Add usage to README로 고쳐 다시 커밋했습니다.
--hard는 커밋과 함께 작업 폴더의 파일까지 앞 커밋으로 되돌립니다. temp.txt를 추가한 커밋을 만든 뒤 실행했습니다.
git reset --hard HEAD~1HEAD is now at 8084244 Add usage to READMElsREADME.md
bye.sh
hello.shtemp.txt가 작업 폴더에서도 지워집니다. --hard로 지운 파일은 git status에도 나오지 않으므로, 실행 전에 남길 변경이 없는지 확인합니다.
reset은 커밋을 기록에서 빼므로, 이미 push해 다른 사람과 함께 쓰는 커밋에는 맞지 않습니다. 그런 커밋은 git revert로 되돌리는 커밋을 새로 만들어 취소합니다.
git revert --no-edit HEAD[main 9836151] Revert "Add usage to README"
Date: Wed Oct 28 22:51:50 2026 +0000
1 file changed, 1 deletion(-)git log --oneline -49836151 (HEAD -> main) Revert "Add usage to README"
8084244 Add usage to README
7027cf4 Merge branch docs
e1ac2cb Describe scriptsRevert 커밋이 맨 위에 새로 쌓이고, 되돌린 커밋 8084244도 기록에 그대로 남습니다. --no-edit는 편집기를 열지 않고 기본 메시지로 커밋하는 옵션입니다.
7️⃣ git push 명령어와 옵션
지금까지 만든 커밋은 서버 안 저장소에만 있습니다. 다른 컴퓨터에서 같은 저장소를 쓰려면 GitHub 같은 원격 저장소를 연결하고, git push로 커밋을 보냅니다.
git remote -v연결된 원격 저장소가 없어 아무것도 출력되지 않습니다. 아래 네 명령은 원격 저장소에 연결하는 명령이라 이번에는 실행하지 않았고, git 공식 문서 기준으로 정리했습니다. 주소의 example.com은 예시 값입니다.
git remote add origin https://example.com/user/project.gitgit remote add는 원격 저장소 주소에 origin이라는 이름을 붙여 등록합니다.
git push -u origin maingit push는 지금 브랜치의 커밋을 원격 저장소로 보냅니다. -u를 붙이면 main 브랜치와 origin의 main이 연결되어, 다음부터는 git push만 입력해도 같은 곳으로 보냅니다.
git pullgit pull은 원격 저장소의 새 커밋을 가져와 지금 브랜치에 병합합니다. 다른 컴퓨터에서 push한 변경을 이 서버로 가져올 때 실행합니다.
git clone https://example.com/user/project.gitgit clone은 원격 저장소를 통째로 내려받아 새 폴더에 저장소를 만들고, 그 주소를 origin으로 등록합니다.
🔲 git 명령어 옵션
📌 주요 옵션: 이 글에서 실행한 결과
| 옵션 | 하는 일 | 이 글에서 본 결과 | |
|---|---|---|---|
| branch -m | 브랜치 이름 바꾸기 | master를 main으로 바꾼 뒤 git status 첫 줄이 On branch main | |
| config --local | 이 저장소의 .git/config에만 기록 | git config --local --list 끝에 user.name=Example User와 user.email=user@example.com 두 줄 | |
| status -s | 파일마다 한 줄로 짧게 | README.md 앞에 A, hello.sh 앞에 ?? | |
| commit -m | 편집기를 열지 않고 메시지를 붙여 커밋 | [main (root-commit) a869c5f] Add README and hello script | |
| diff --staged | 스테이징 영역에 담은 변경과 마지막 커밋의 차이 | -echo Hello와 +echo Hello, Git 두 줄 | |
| log --oneline | 커밋마다 짧은 해시와 메시지 한 줄 | ae75c08 (HEAD -> main) Change greeting과 a869c5f 두 줄 | |
| log --graph | 왼쪽에 커밋 줄기를 그림 | docs 쪽 줄기가 병합 커밋 7027cf4에서 다시 합쳐짐 | |
| log --all | 모든 브랜치의 커밋을 함께 | feature 브랜치의 b2f2dce까지 세 줄 | |
| log -숫자 | 최근 커밋을 그 수만큼 | -4로 9836151부터 e1ac2cb까지 네 줄 | |
| switch -c | 브랜치를 만들고 바로 그 브랜치로 이동 | Switched to a new branch 'feature' | |
| branch -d | 병합한 브랜치 지우기 | Deleted branch feature (was b2f2dce). | |
| restore --staged | 스테이징 영역에서만 빼고 작업 폴더의 변경은 남김 | git status -s의 M이 앞 칸에서 뒤 칸으로 | |
| reset --soft | 커밋만 취소하고 변경은 스테이징 영역에 남김 | Add usage 커밋이 사라지고 README.md 앞 칸에 M | |
| reset --hard | 커밋과 작업 폴더의 파일까지 되돌림 | HEAD is now at 8084244 Add usage to README, temp.txt도 사라짐 | |
| revert --no-edit | 편집기를 열지 않고 기본 메시지로 되돌리는 커밋 | [main 9836151] Revert “Add usage to README” |
📎 그 밖의 옵션: 공식 매뉴얼 기준
| 옵션 | 하는 일 | |
|---|---|---|
| config --global | 저장소의 .git/config 대신 사용자 홈 폴더의 ~/.gitconfig에 기록 | |
| add -A, --all | 작업 폴더 전체의 추가, 수정, 삭제를 스테이징 영역에 반영 | |
| add -p, --patch | 바뀐 덩어리(hunk)를 하나씩 보며 골라 담기 | |
| commit -a, --all | 고치거나 지운 파일을 자동으로 담아 커밋, git이 모르는 새 파일은 빠짐 | |
| commit --amend | 마지막 커밋을 새 커밋으로 바꿔 씀 | |
| branch -a, --all | 원격 추적 브랜치까지 함께 출력 | |
| branch -D | 병합하지 않은 브랜치도 강제로 지우기(--delete --force) | |
| checkout -b | 새 브랜치를 만들고 그 브랜치로 이동 | |
| merge --abort | 충돌로 멈춘 병합을 취소하고 병합 전 상태로 | |
| merge --no-ff | Fast-forward로 끝낼 수 있어도 병합 커밋을 만듦 | |
| reset --mixed | 옵션을 생략하면 이 동작, 커밋과 스테이징 영역을 되돌리고 작업 폴더의 변경은 남김 | |
| log --stat | 커밋마다 바뀐 파일과 바뀐 줄 수 요약 | |
| push -u, --set-upstream | 보낸 브랜치를 원격 브랜치와 연결해, 인자 없는 git pull이 그 브랜치를 사용 | |
| pull -r, --rebase | 가져온 뒤 병합 대신 원격 브랜치 위로 지금 브랜치를 rebase |
🔲 git 명령어 시뮬레이터
아래 시뮬레이터의 가상 서버에서 git 명령을 직접 입력해 볼 수 있습니다. /root/project 폴더에서 git init부터 시작해 커밋과 브랜치 병합, 되돌리기까지 순서대로 실행합니다. 원격 저장소 명령은 실행하지 않고 안내만 나옵니다.
🔢 FAQ & 추천 콘텐츠
Linux · 파일 동기화
리눅스 Rsync 명령어: 옵션 | 사용 예시
원본과 대상을 비교해 달라진 파일만 보내는 rsync로, 로컬 폴더와 SSH로 연결한 서버 사이를 맞추는 방법입니다.
Linux · 편집기
[Linux] 리눅스 vi 명령어 정리 | Vim 3가지 모드 및 비주얼 모드
명령 모드와 입력 모드가 나뉜 vi에서 지금 모드를 확인하고 저장·종료하는 명령을 표로 정리한 글입니다.
Linux · 권한
리눅스 퍼미션(4,2,1)과 소유권 | chmod, chown, umask 명령어 | 스티키 비트
파일 권한 숫자 4·2·1과 소유권, chmod·chown·umask 명령으로 권한을 바꾸는 방법입니다.
ℹ️ 제휴 안내
본 사이트의 콘텐츠에는 제휴 링크가 포함되어 있습니다. 방문자가 이 링크를 통해 상품 또는 서비스를 구매하면 본 사이트는 판매처로부터 수수료를 지급받습니다. 이 과정에서 구매자가 지불하는 금액(이벤트 할인 시 금액이 내려갑니다↓)은 오르지 않습니다. 게시된 가격·할인·재고 정보는 작성 시점 기준이며 실제와 다를 수 있으므로, 구매 전 판매처에서 최종 확인하시기 바랍니다. 상품 선정과 평가는 자체 기준에 따라 작성되며, 수수료 지급 여부가 소개 순서나 평가 내용에 영향을 주지 않습니다.