반응형

Git과 GitHub를 처음 접하시나요? 이 가이드에서는 Git의 핵심 개념과 자주 쓰는 명령어들을 쉽게 풀어보겠습니다. 어려운 용어는 피하고, 실제 사용 예제를 중심으로 설명할게요. 이 글을 따라 하면 로컬에서 Git으로 버전 관리를 시작하고, 원격 저장소(GitHub 등)를 통해 다른 사람과 협업하는 방법까지 감을 잡을 수 있습니다. 편안한 마음으로 천천히 살펴보세요! 😊

1. Git이란?

Git은 버전 관리 시스템의 한 종류입니다. 쉽게 비유하면 코드의 타임머신이에요. 개발을 하다 보면 파일을 여러 버전으로 저장해두고 싶을 때가 많은데, Git은 이러한 변경 이력을 스냅샷처럼 기록해 둡니다. 덕분에 언제든 이전 상태로 돌아가거나 변경 내용을 비교할 수 있고, 여러 명이 동시에 작업해도 충돌을 관리할 수 있죠.

  • 버전 관리: 파일이 시간에 따라 어떻게 바뀌었는지 기록합니다. 예전에는 파일명을 project_v1.txt, project_v2.txt 이렇게 붙여가며 관리했다면, Git을 쓰면 그런 번거로운 일을 자동으로 해줍니다.
  • 분산 형상 관리: Git은 분산형 시스템이라서, 모든 참여자가 동일한 전체 이력을 복제해 갖고 있습니다. 인터넷이 안 되는 상황에서도 내 컴퓨터에 완전한 히스토리가 있기 때문에 작업이 가능하고, 나중에 다시 동기화할 수 있어요.
  • GitHub와 Git: GitHub는 Git 저장소를 온라인에서 호스팅 해주는 서비스입니다. 쉽게 말해, Git이 자동차라면 GitHub는 고속도로 휴게소 같은 역할이에요. 내 컴퓨터의 Git 저장소를 GitHub에 올려 두면, 다른 사람과 공유하거나 백업할 수 있습니다. (GitHub 외에도 GitLab, Bitbucket 같은 서비스도 있어요.)

2. Git 기본 명령어

이제 Git의 기본적인 사용 흐름을 알아봅시다. 일반적인 작업 흐름은 저장소 초기화 → 변경 파일 추가(Stage) → 커밋(Commit) 입니다. 그 사이사이에 현재 상태를 확인하거나(commit 내역을 조회)하는 일도 빈번하죠. 아래에 소개하는 명령어들이 바로 이러한 Git의 기초를 담당하는 명령어들입니다.

저장소 초기화 (git init)

$ git init

현재 작업 중인 디렉터리를 **Git 저장소(repository)**로 초기화합니다. 이 명령을 실행하면 해당 폴더에 숨김 폴더 .git이 생성되어요. .git 폴더는 Git이 모든 버전 이력을 저장하는 데이터베이스와 같은 곳입니다. 한 번 git init으로 초기화한 폴더에서는 이후부터 Git 명령어들을 사용할 수 있게 됩니다. 보통 새로운 프로젝트를 시작할 때 한 번만 실행하면 되며, 이미 Git 저장소로 **클론(clone)**해온 폴더라면 git init을 따로 할 필요가 없습니다.

 

예시: 새 폴더를 만들어 Git 저장소로 초기화하기

$ mkdir my-project && cd my-project
$ git init # 초기화(/path/to/my-project/.git/)

위처럼 my-project 폴더가 Git 저장소로 초기화되어 .git 폴더가 생성된 것을 볼 수 있습니다.

파일 스테이징 (git add)

$ git add <파일명>

작업 중인 변경사항을 **스테이징 영역(Stage)**에 추가하는 명령어입니다. 쉽게 말해, “이 파일을 다음 커밋에 포함시켜 줘” 하고 Git에게 알려주는 단계입니다. 예를 들어 git add index.html이라고 하면 index.html 파일을 커밋할 목록에 올려둔다는 뜻이에요.

  • git add . (마침표): 현재 디렉터리의 모든 변경 파일을 한꺼번에 Stage에 올립니다. 새로 생성했거나 수정된 모든 파일들을 일일이 추가하지 않고 한 번에 추가할 때 편리합니다.
  • git add -A 또는 git add --all: 프로젝트 내의 모든 변경사항을 Stage에 추가합니다. 일반적으로 git add .와 거의 동일하게 사용됩니다.

스테이징을 하는 이유는 원하는 변경만 골라서 커밋하기 위함입니다. Git은 기본적으로 여러분이 git add로 지정한 파일만 추적하므로, 실수로 넣고 싶지 않은 변경은 Stage에 올리지 않으면 커밋되지 않습니다. (아직 Git이 추적하지 않는 새로운 파일들은 Untracked files라고 하며, 이때도 git add를 통해 Git에게 “이 파일을 추적해!” 하고 알려줘야 합니다.)

커밋 (git commit)

$ git commit -m "커밋 메시지 작성"

**커밋(commit)**은 Stage에 올라온 변경사항들을 하나의 버전으로 확정해서 기록하는 작업입니다. git commit을 실행하면 지금까지 Stage에 모아둔 파일들의 스냅샷을 찍어 **하나의 버전(리비전)**으로 저장합니다. 이때 -m "메시지" 옵션을 사용해 해당 버전에 대한 설명을 남길 수 있어요. 예를 들어 git commit -m "회원 로그인 기능 추가"와 같이 명령을 입력하면, "회원 로그인 기능 추가"라는 메시지와 함께 현재 Stage의 내용이 하나의 커밋으로 영구 저장됩니다.

  • 커밋 메시지: 나중에 기록을 볼 때 이해하기 쉽게, 어떤 변경을 했는지 간략히 적어주세요. 예) "버그 수정: 로그인 실패 시 오류 메시지 표시", "Docs: README에 프로젝트 설명 추가".
  • 주의: 만약 -m 옵션을 생략하고 git commit만 실행하면, Git이 기본 에디터를 열어서 메시지를 입력하게 합니다. 초심자 분들은 갑자기 Vim 같은 에디터 화면이 열려 당황할 수 있는데, 이럴 때는 :wq로 저장 종료하거나 터미널에서 빠져나오시면 됩니다. 번거로우니 처음에는 -m 옵션으로 메시지를 함께 작성하는 습관을 들이는 게 좋아요.
  • 작게 자주 커밋하기: 기능 하나를 완성한 후, 또는 코드를 일정 부분 수정한 후에는 커밋을 자주 해두는 것이 좋습니다. 커밋을 잘게 나눌수록 나중에 문제가 생겼을 때 특정 지점으로 되돌아가기 쉽고, 다른 협업자와 작업 내역을 파악하기도 수월해집니다.

변경 사항 확인 (git status, git log)

작업 중에 현재 Git 상태커밋 이력을 확인하고 싶을 때가 있습니다. 아래 두 명령어는 Git 사용자의 든든한 친구입니다:

  • git status : 현재 저장소의 상태를 보여줍니다. 어떤 파일이 새로 생성되어 추적되고 있지 않은지(Untracked), 어떤 파일이 수정되었지만 Stage에 올리지 않았는지, 어떤 파일이 Stage에 올라와 있는지 등을 색깔과 함께 상세히 알려줍니다. 커밋하기 전에 git status를 습관처럼 입력해 보면 "아, 이 파일을 아직 add 안 했구나"하거나 "커밋할 변경사항이 없네" 등을 바로 알 수 있어요.
  • git log : 지금까지 만든 커밋들의 히스토리를 보여줍니다. 최근 커밋부터 순서대로 커밋 해시(고유 ID), 작성자, 날짜, 메시지를 출력하지요. 이를 통해 프로젝트의 변경 이력을 추적할 수 있습니다.
    • 너무 많은 로그가 보이면 q 키를 눌러 빠져나올 수 있습니다.
    • 옵션 Tip: git log --oneline --graph를 쓰면 각 커밋을 한 줄로 요약해주고, 브랜치 흐름을 아스키 그래프로 보여줘서 히스토리를 한눈에 보기 편합니다.

3. 원격 저장소 관리

이제 로컬에서 버전 관리를 했다면, **원격 저장소(remote repository)**를 사용해보겠습니다. 원격 저장소는 인터넷상의 Git 저장소로, 대표적으로 GitHub를 많이 사용합니다. 원격 저장소를 연결해두면 내 컴퓨터에서 만든 커밋을 다른 사람들과 공유하거나, 반대로 다른 사람이 올린 변경사항을 받아올 수 있습니다. 즉, 협업과 백업을 위해 원격 저장소를 활용하게 됩니다. 아래 명령어들은 원격 저장소를 추가하고 동기화하는 데 사용됩니다.

원격 저장소 연결 (git remote add)

$ git remote add <원격별칭> <원격URL>

내 로컬 Git 저장소에 원격(remote) 저장소를 등록하는 명령어입니다. 일반적으로 원격 저장소를 처음 추가할 때 한 번 실행합니다. <원격별칭> 부분에는 원격 저장소의 이름을 정해줄 수 있는데, 관례적으로 **origin**이라는 이름을 많이 사용합니다. <원격URL>에는 Git 원격 저장소의 주소(예: GitHub 저장소 HTTPS 또는 SSH 주소)를 넣습니다.

예를 들어, GitHub에 my-project라는 원격 저장소를 만들어두었다면 다음과 같이 연결할 수 있습니다:

$ git remote add origin https://github.com/사용자이름/my-project.git

위 명령을 실행하면 origin이라는 이름으로 GitHub의 원격 저장소를 등록합니다. 이후로는 origin을 가리켜서 원격 저장소와 통신하게 됩니다. (원격이 제대로 추가되었는지 확인하려면 git remote -v 명령으로 등록된 URL 목록을 볼 수 있어요.)

원격 저장소에서 가져오기 (git fetch, git pull)

원격 저장소에 다른 사람의 커밋(또는 내가 다른 곳에서 한 작업)이 올라와 있다면, 이를 내 로컬로 가져오는 작업이 필요합니다. git fetch와 git pull이 그 역할을 합니다.

  • git fetch : 원격 저장소의 최신 커밋들을 가져와서 로컬 저장소의 데이터만 업데이트합니다. 이 명령을 실행해도 내 작업 디렉토리의 파일들은 바로 변경되지 않고, 받은 커밋들은 일단 로컬 저장소의 기록으로 저장만 됩니다. 보통 fetch 후에는 git log 등을 통해 어떤 변경사항이 들어왔는지 확인하고, 필요한 경우 수동으로 병합합니다.
    Tip: git fetch는 말 그대로 "가져오기"만 하기 때문에, 가져온 이후 **git merge**를 통해 내 현재 브랜치와 합쳐야 변경사항이 반영됩니다. fetch를 사용하면 원격의 변화를 바로 내 코드에 적용하지 않고도 미리 살펴볼 수 있어서, 충돌 상황을 예측하거나 코드 검토를 할 수 있다는 장점이 있어요.
$ git fetch origin # origin 원격의 최신 변화들을 가져오기
  • git pull : 원격 저장소의 변경사항을 가져온 뒤 자동으로 내 현재 브랜치에 병합까지 한 번에 수행합니다. 내부적으로는 git fetch + git merge를 줄여 놓은 동작이에요. 그래서 내가 작업 중인 브랜치의 원격 업데이트를 곧바로 내 작업 폴더에 반영해 줍니다. 간단히 git pull만 쳐도 현재 체크아웃한 브랜치의 추적 중인 원격 브랜치(changes)를 알아서 가져와 병합합니다. 협업 시에는 보통 새로운 작업을 시작하기 전에 git pull로 최신 코드를 받아 내 로컬을 업데이트하는 습관이 중요합니다. 만약 가져온 변경사항과 내 로컬 수정사항이 충돌(conflict)하면, Git이 어떤 파일에 충돌이 났는지 알려주고 수동으로 충돌을 해결하도록 안내합니다.
$ git pull origin main # origin 원격의 main 브랜치 변경사항 가져와 현재 브랜치에 바로 병합

원격 저장소에 업로드 (git push)

$ git push <원격별칭> <브랜치명>

로컬에서 커밋한 내용을 원격 저장소로 업로드(밀어넣기) 하는 명령어입니다. <원격별칭>에는 보통 origin을, <브랜치명>에는 보내고 싶은 로컬 브랜치 이름을 적습니다. 예를 들어 현재 main 브랜치에서 작업했고 그 내용을 GitHub의 원격 origin에 반영하고 싶다면:

$ git push origin main

라고 실행하면 됩니다. 이 명령을 수행하면 내 로컬 main 브랜치의 새 커밋들이 원격 origin의 main 브랜치로 업로드되어, GitHub상의 저장소에도 동일한 이력이 기록됩니다. 이제 이 원격 저장소를 보는 다른 동료들도 내가 푸시한 최신 커밋을 볼 수 있게 되죠.

  • 처음 push 하는 경우: 로컬 브랜치를 원격에 처음 푸시할 때는 -u 옵션을 함께 사용하는 것이 편리합니다. 예를 들어 git push -u origin main으로 처음 푸시하면, 로컬 main 브랜치와 원격 main 브랜치가 연동되면서 이후로는 git push나 git pull 명령을 별도 인자 없이도 사용할 수 있게 설정됩니다. (-u는 --set-upstream의 약어로, 추적할 원격 브랜치를 설정하는 옵션입니다.)
  • 주의: git push는 기본적으로 원격에 내 로컬 변경사항을 추가하는 행위입니다. 원격에 내가 가진 커밋보다 앞선 변경이 있다면 push가 거부됩니다("fetch first" 에러). 이때는 먼저 git pull로 최신 원격 변경을 가져와 병합한 뒤 다시 push 해야 합니다.

4. 브랜치(branch) 관리

Git의 강력한 기능 중 하나가 바로 **브랜치(branch)**입니다. 브랜치는 독립된 작업 흐름을 만들기 위해 사용합니다. 마치 평행우주처럼, 동일한 프로젝트 내에서 여러 갈래의 타임라인을 만들어주는 것이죠. 예를 들어, 새로운 기능을 개발할 때 기존 코드를 그대로 두고 별도의 브랜치를 만들어 실험할 수 있습니다. 작업이 끝나면 다시 메인(main) 브랜치에 합칠 수 있기 때문에, 여러 작업이 동시에 진행되어도 서로 충돌을 줄이며 관리할 수 있습니다.

브랜치 생성 및 전환 (git branch, git checkout -b)

  • 브랜치 생성: 위 명령으로 현재 체크아웃된 브랜치로부터 새로운 브랜치를 만들어냅니다. 예를 들어 git branch feature/login이라고 하면 현재 작업 중인 커밋 시점에서 feature/login이라는 이름의 브랜치가 생성됩니다. 아직 그 브랜치로 **이동(checkout)**한 것은 아니고, 브랜치 목록에 추가만 된 상태예요. git branch 명령에 인자 없이 실행하면 현재 저장소에 존재하는 모든 브랜치 목록을 보여주며, 그중 현재 체크아웃된 브랜치 앞에는 * 표시가 붙어 있습니다.
$ git branch 새로운브랜치이름
  • 브랜치 전환(체크아웃): 이 명령을 실행하면 작업 중인 커밋 포인터(HEAD)가 해당 브랜치로 이동하고, 내 작업 디렉터리의 파일들도 그 브랜치의 최신 커밋 상태로 바뀝니다. 즉, 코드베이스를 선택한 브랜치의 시점으로 스위치 하는 것이죠. 새로운 브랜치를 만든 직후에는 잊지 말고 git checkout으로 그 브랜치에 이동해야 해당 브랜치에서 작업을 시작할 수 있습니다.
$ git checkout 브랜치이름
  • 생성과 전환 한 번에: git branch + git checkout을 한 번에 하는 단축키라고 생각하면 됩니다. 위와 같이 -b 옵션을 주면 새 브랜치를 만들고 즉시 그 브랜치로 이동합니다. 신규 기능이나 버그 수정을 시작할 때 자주 사용하는 패턴이에요. 예를 들어, git checkout -b feature/comment-ui라고 입력하면 feature/comment-ui 브랜치를 만들고 곧바로 그 브랜치로 전환합니다.
$ git checkout -b 새로운브랜치이름

브랜치 이름 짓기 Tip: 브랜치 이름은 해당 브랜치에서 할 작업을 잘 나타내도록 짓는 것이 좋습니다. 예를 들어 새로운 댓글 기능 작업 브랜치는 feature/comment-ui, 버그 수정 브랜치는 bugfix/login-error처럼요. 이름만 보고도 무슨 작업용인지 팀원들이 알아볼 수 있도록 하면 협업에 도움이 됩니다.

브랜치 병합 (git merge / git rebase)

브랜치를 만들어 작업을 했다면, 결국 나중에 그 결과물을 다시 메인 브랜치 등에 **병합(merge)**해야 합니다. Git에서는 브랜치를 합치는 방법으로 mergerebase 두 가지를 주로 사용합니다. 둘 다 목표는 브랜치의 내용을 다른 브랜치에 반영하는 것이지만, 동작 방식이 다릅니다.

  • git merge : 현재 체크아웃된 브랜치에 다른 브랜치의 변경사항을 합치는 명령어입니다. 예를 들어 우리가 feature/login 브랜치에서 어떤 기능을 완성했다면, 메인 브랜치(main)로 돌아와서 git merge feature/login을 실행해 보세요. 위처럼 하면 메인 브랜치에 feature/login 브랜치의 커밋들이 합쳐집니다. 만약 메인 브랜치가 그동안 변동이 없었다면 Fast-forward라고 해서 단순히 메인의 헤드가 feature 브랜치의 끝으로 앞으로 움직입니다. 하지만 두 브랜치에 서로 다른 변경이 있었다면 merge commit이라는 특별한 커밋이 생성되어 두 갈래의 작업 내역을 하나로 합칩니다. Merge 과정에서 충돌(conflict)이 발생하면 Git이 알려주며, 해당 파일을 열어 수동으로 충돌 부분을 고쳐주면 됩니다. 수정 후 git add로 충돌 해결된 파일을 Stage에 올리고 git commit 하면 병합 커밋이 완성됩니다.
$ git checkout main # 메인 브랜치로 이동
$ git merge feature/login # feature/login 브랜치의 작업을 메인에 병합
  • git rebase : 기능은 병합과 같지만, 히스토리를 다시 쓰는 방법입니다. 예를 들어, feature/login 브랜치를 main에 rebase 한다는 것은 feature/login 브랜치의 시작점을 최신 메인 브랜치 커밋으로 옮겨서 마치 처음부터 메인 브랜치에서 시작한 것처럼 재배치하는 것입니다. 이 명령을 실행하면 feature 브랜치의 커밋들이 메인 브랜치의 가장 최신 커밋 뒤로 차례로 재적용됩니다. 결과적으로 merge와 달리 브랜치 히스토리가 일직선으로 깔끔해지는 효과가 있습니다. 다만 rebase는 기존 커밋의 기반을 바꾸기 때문에 히스토리를 변경하는 작업입니다. 이미 원격에 공유된 브랜치에 대해서 rebase를 하면 다른 협업자들의 기록과 달라져 혼란이 생길 수 있으므로, 보통 로컬에서 혼자 작업 중인 브랜치에 한해서 사용하는 게 좋아요.
$ git checkout feature/login # feature 브랜치에 머문 상태에서
$ git rebase main # main 브랜치의 최신 커밋으로 베이스 변경

정리하면, merge는 기존 히스토리를 그대로 두고 "합쳤다"는 기록(merge commit)을 남기는 방식이고, rebase는 히스토리를 직선으로 다시 그려 합치는 방식입니다. 처음 Git을 익힐 때는 보통 git merge로 병합을 많이 하고, 어느 정도 익숙해지면 히스토리를 깔끔하게 유지하고 싶을 때 git rebase를 선택적으로 사용하곤 합니다. 상황과 팀 규칙에 맞게 둘 중 편한 방법을 쓰시면 됩니다.

브랜치 삭제 (git branch -d)

$ git branch -d 브랜치이름

더 이상 필요 없는 브랜치는 삭제해서 정리할 수 있습니다. 예를 들어, feature/login 브랜치를 메인에 다 합쳤다면 해당 브랜치는 완료된 것이니 삭제해도 되겠죠. git branch -d feature/login 명령을 실행하면 로컬에서 feature/login 브랜치를 지웁니다.

  • -d 옵션은 이미 병합된(branch merged) 브랜치만 삭제합니다. 만약 해당 브랜치가 아직 다른 곳에 병합되지 않은 상태라면, 혹시 중요한 작업을 실수로 날릴까 봐 Git이 삭제를 거부합니다. 이때 확실히 삭제하고 싶으면 대문자 -D 옵션을 사용하면 강제 삭제가 가능합니다. (주의: -D로 지운 브랜치는 복구가 어려울 수 있으니 신중히!)
  • 브랜치를 삭제해도 그 브랜치의 커밋 내용이 다른 브랜치에 모두 합쳐져 있다면 이력은 남아 있으므로 안심해도 됩니다. 원격 저장소에 있는 브랜치도 지우고 싶다면 git push origin --delete 브랜치이름 명령으로 원격 브랜치도 제거할 수 있습니다.

5. 커밋 수정 및 되돌리기

Git을 쓰다 보면 가끔 커밋을 실수로 잘못 작성하거나, 이전 상태로 되돌리고 싶을 때가 있습니다. Git은 이미 한 커밋을 수정하거나 취소할 수 있는 강력한 도구들을 제공합니다. 하지만 이 기능들은 이력을 변경하기도 하므로, 올바른 상황에서 조심해서 사용하는 것이 중요합니다.

마지막 커밋 수정 (git commit --amend)

$ git commit --amend -m "새로운 커밋 메시지"

방금 한 마지막 커밋을 수정할 때 사용합니다. 흔한 사용 사례는 커밋 메시지를 잘못 입력했거나, 커밋에 빠뜨린 변경사항이 있을 때입니다. --amend 옵션을 붙여 커밋을 하면 이전 커밋을 덮어쓰게 됩니다.

예를 들어, 파일 몇 개를 커밋했는데 빠뜨린 파일이 하나 있어서 새로 Stage에 올린 경우, git commit --amend를 실행하면 방금 전 커밋 + 신규 Stage 내용을 합쳐 하나의 커밋으로 수정합니다. 커밋 메시지도 다시 입력하라고 나오는데, -m 옵션을 주면 바로 새 메시지로 대체됩니다 (옵션 없이 실행하면 편집기에서 기존 메시지를 수정할 수 있게 됩니다).

  • 주의: Amend는 로컬 히스토리를 수정하는 것이므로, 이미 push까지 한 커밋에 대해 amend를 하면 원격과 내 로컬 이력이 달라져버립니다. 이렇게 되면 협업자들과 충돌이 생길 수 있으니, 이미 원격에 공유한 커밋은 가급적 amend 하지 않는 것이 좋습니다. (만약 꼭 수정해야 한다면, force push가 필요하지만 이는 매우 주의해야 하는 작업입니다.) 로컬에서 커밋하고 아직 push 하지 않은 상태에서 작은 실수를 고치는 용도로만 쓰길 권장합니다.

특정 커밋 되돌리기 (git reset, git revert)

무언가 잘못된 변경을 취소하거나, 아예 지난 커밋으로 돌아가고 싶다면 reset이나 revert를 사용합니다. 이 둘은 모두 이전 상태로 돌아간다는 공통점이 있지만 작동 방식과 용도가 다릅니다.

  • git reset : 현재 브랜치의 HEAD(커밋 포인터)를 과거의 특정 커밋으로 되돌리는 명령어입니다. 예를 들어 지난 커밋을 취소하고 그 상태로 돌아가고 싶다면 git reset HEAD1은 현재 HEAD의 한 칸 이전 커밋을 가리킵니다.) Reset을 하면 지정한 커밋 이후의 커밋들은 내 로컬 브랜치 역사에서 사라지게 됩니다.
    • 기본적으로 git reset은 --mixed 모드로 동작하는데, 이는 커밋은 취소하되 취소된 커밋에서 변경된 파일들은 워킹 디렉터리에 그대로 남겨둡니다. 예를 들어 git reset HEAD~1을 하면 마지막 커밋을 지우지만, 해당 커밋에서 변경되었던 파일 내용은 지워지지 않고 파일 수정 상태로 남아 있어요. 이 상태에서 필요하면 수정 보완 후 다시 커밋할 수 있죠.
    • 반대로 --hard 모드를 쓰면 워킹 디렉터리의 변경 내용까지 포함해서 완전히 지정한 커밋 시점으로 돌아갑니다. git reset --hard HEAD~1을 하면 마지막 커밋을 없애고 그 내용 변경사항도 전부 버려지는 것이죠. 아주 조심해야 하는 옵션으로, 이 경우 사라진 변경사항은 복구하기 어렵습니다.
    • Reset은 로컬 히스토리를 지우는 행위이기 때문에, 이미 push 한 커밋을 reset으로 지우면 원격과 충돌이 생겨 push가 거부됩니다. 이때는 강제로(push --force) 푸시해야 하는데, 협업 상황에서는 금기시됩니다. 따라서 reset은 주로 아직 원격에 올리지 않은 내 로컬 커밋을 취소할 때 사용합니다.
  • git revert : 특정 커밋이 도입한 변경 사항을 반대 변경으로 취소하는 새 커밋을 만드는 명령어입니다. 쉽게 말해, 이력을 지우지 않고 *되돌리는 내용의 "취소 커밋"*을 추가하는 것입니다. 예를 들어 방금 한 커밋을 무르고 싶다면 git revert HEAD라고 실행해 보세요. 이렇게 하면 Git이 자동으로 해당 커밋의 변경내역을 역으로 적용하려 시도하고, 성공하면 그 결과를 새로운 커밋으로 기록합니다. revert 커밋의 메시지는 기본적으로 "Revert '원래 커밋 메시지'" 형태로 표시돼서 어떤 커밋을 되돌렸는지 알 수 있습니다.
    • Revert의 장점은 과거 기록은 건드리지 않고 문제 된 변경만 취소한다는 점입니다. 따라서 이미 공유된 이력에도 적용할 수 있으며, 협업 중에도 안전하게 취소 작업을 할 수 있습니다.
    • 한 가지 유의할 것은, revert는 그 커밋이 변경한 내용을 정확히 뒤집는 작업이므로, 만약 되돌리려는 커밋 이후에 해당 부분이 또 수정되었다면 충돌이 날 수도 있습니다. 이러한 경우에도 Git이 충돌을 알려주며 수동 해결을 요구합니다.
$ git revert <되돌릴커밋해시>

요약하면, reset은 이력을 지워서 되돌리는 것이고 (과거로 타임슬립), revert는 이력 위에 "여기서 이 변경을 취소한다"는 새 커밋을 쌓는 방식입니다. 혼자 하는 작업이거나 방금 전 커밋을 없애는 정도라면 reset을 쓰기도 하지만, 공동 작업이나 이미 원격에 올라간 변경을 취소할 때는 revert를 사용하는 편이 안전합니다.

6. 변경 사항 임시 저장 (Stash)

코딩을 하다 보면 현재 진행 중인 작업을 다 완료하지 못했는데, 갑자기 다른 브랜치로 급히 전환해야 할 때가 있습니다. **Git Stash(스태시)**는 그런 상황에서 유용한 도구예요. 커밋하기 애매한 작업 중인 변경사항들을 잠시 어딘가에 치워놓고(임시 저장), 나중에 다시 가져올 수 있게 해 줍니다. 마치 작업하던 메모를 책상 서랍에 잠깐 넣어두고 책상을 깨끗이 비우는 느낌이라고 할까요?

  • 임시 저장하기 – git stash: 이 명령을 실행하면 현재 Working Directory에서 추적 중인 모든 변경사항(수정되었거나 Stage에 올라간 파일들)을 임시 공간에 저장하고, 워킹 디렉터리를 마지막 커밋 상태로 되돌립니다. 즉, 변경 파일들이 사라지는 것처럼 보이지만 걱정하지 마세요! 변경 내용은 stash에 안전하게 보관된 것입니다. 연달아 몇 번이고 stash를 쌓아둘 수도 있으며, git stash list로 쌓여 있는 stash들의 목록을 볼 수 있습니다.
$ git stash
  • 임시 저장 불러오기 – git stash pop: 가장 최근에 stash에 넣어둔 변경사항을 다시 불러옵니다. 이 명령을 실행하면 워킹 디렉터리에 해당 변경사항들이 복원되고, 복원과 동시에 그 stash 항목은 목록에서 제거(drop)됩니다. (만약 내용 확인을 위해 제거하지 않고 가져오고 싶다면 git stash apply를 사용할 수 있는데, 초보 단계에서는 pop만 알아도 충분합니다.)
$ git stash pop
  • 임시 저장 삭제 – git stash drop: 특정 stash 항목을 버리려면 drop을 사용합니다. 인자를 붙이지 않으면 가장 최근 stash 항목을 삭제합니다. (git stash list로 확인한 인덱스 번호를 붙여 git stash drop stash@{번호}처럼 삭제할 수도 있어요.) 이미 pop으로 가져오면 자동 삭제되지만, 혹시 stash를 가져온 후 남아있는 항목이나 필요 없어진 저장 내역이 있다면 drop으로 깔끔히 지울 수 있습니다.
$ git stash drop

활용 팁: Stash는 작업을 중단해야 할 때 유용하지만, 장기간 여러 스태시를 쌓아두는 것은 좋지 않습니다. 잊고 지낼 수 있고, 나중에 콘텍스트를 잃을 수 있거든요. 가능한 한 빨리 stash에 넣은 변경은 다시 적용해서 커밋하거나 버리는 정리를 하세요. 또한 stash에는 메시지를 붙일 수도 있습니다 (git stash save "메시지" 또는 최신 Git에서는 git stash push -m "메시지" 사용) – 나중에 무슨 작업이었는지 기억하기 쉽겠죠?

7. .gitignore 활용

프로젝트를 하다 보면 버전 관리가 불필요한 파일들도 생깁니다. 예를 들어, 로그 파일이나 개인 설정 파일, 빌드 결과물(binary) 등은 굳이 Git으로 관리할 필요가 없죠. 이런 것들은 실수로 커밋되는 걸 방지하기 위해 .gitignore 파일에 등록합니다. .gitignore는 이름 그대로 Git이 "무시해야 할 파일/폴더 목록"을 적어두는 특별한 파일입니다.

프로젝트 루트 디렉토리에 .gitignore라는 이름의 파일을 만들고, Git에 올리지 않을 파일 패턴들을 한 줄씩 써주면 됩니다. 예를 들어 다음과 같습니다:

# .gitignore 예시
# 로그 파일 무시 *.log 
# 개인 개발환경 설정 파일 무시 config.yaml 
# 빌드 결과물 디렉토리 무시 dist/

위 예시는 확장자가 .log인 모든 파일들과, config.yaml이라는 이름의 파일, 그리고 dist 폴더 내의 모든 내용을 Git에서 추적하지 않도록 지정한 것입니다. 이렇게 .gitignore에 적힌 패턴에 해당하는 파일들은 git status를 해도 Untracked files에 나타나지 않고, git add .를 해도 자동으로 제외되므로 안심할 수 있어요.

  • .gitignore 파일 자체도 일반 파일처럼 Git에 커밋해서 팀원들과 공유할 수 있습니다. 모두가 같은 규칙으로 불필요한 파일을 올리지 않도록 약속하는 것이죠.
  • 주의: 이미 커밋된 파일을 .gitignore에 추가해도 이전 커밋에서 제거되지는 않습니다. 그런 파일은 일단 수동으로 git rm --cached 파일명 등으로 한 번 추적을 끊어준 뒤 .gitignore에 올려야 효과가 있습니다.
  • 각 개발 환경이나 언어별로 추천 .gitignore 템플릿이 있습니다. 예를 들어 Node.js 프로젝트라면 node_modules/ 폴더를 무시해야 하고, Python 프로젝트라면 *.pyc 파일을 무시하는 등 항목이 있겠죠. 초기 프로젝트 생성 시 GitHub에서 제공하는 .gitignore 템플릿을 사용하면 편리합니다.

지금까지 Git과 GitHub의 핵심 명령어들을 살펴보았습니다. 처음에는 낯설고 복잡해 보일 수 있지만, 하나씩 해보다 보면 금세 익숙해질 거예요. 😃 여기 나온 명령어들만 잘 알아두셔도 혼자서 버전 관리를 하는 데에는 큰 문제가 없을 것입니다. 나아가 GitHub 같은 원격 저장소와 함께 활용하면 협업도 훨씬 수월해집니다.

마지막으로, Git은 굉장히 풍부한 기능을 가진 도구입니다. 필요해지면 git cherry-pick이나 git tag, git reflog처럼 더 고급 명령어들도 접하게 될 텐데요. 그때그때 공식 문서나 커뮤니티 자료를 참고하며 천천히 배우면 됩니다. 우선은 여기 소개된 기본 명령어들을 직접 따라 치면서 익혀보세요. 실습만큼 빨리 배우는 방법은 없답니다! Git과 함께 즐거운 코딩하시길 바랍니다. 🚀

728x90
반응형