Git 저장소: git init으로 만들고 remote 연결하기
Git 저장소는 프로젝트 폴더와 숨김 폴더 .git을 합친 것으로, 커밋, 브랜치, 태그, 설정 같은 전체 히스토리가 .git 안에 저장됩니다. git init 명령으로 폴더에서 저장소를 만들고, git clone으로 기존 저장소를 받으며, git remote add origin 주소로 원격 저장소를 연결합니다.
Git 저장소는 Git이 변경 사항을 추적하는 프로젝트입니다. 실제로는 평범한 폴더에 있는 파일들과 숨김 폴더 .git을 합친 것입니다. .git 안에는 커밋, 브랜치, 태그, 설정을 포함한 전체 히스토리가 있습니다. .git을 지우면 파일만 남고, 과거 버전은 모두 사라집니다.
저장소의 구성 요소
Git으로 작업할 때는 변경이 이동하는 세 영역을 머릿속에 두면 편합니다.
- 작업 디렉터리(working tree) — 여러분이 보고 편집하는 파일;
- 인덱스(staging area) —
git add로 변경을 올려 두는 다음 커밋의 초안; - 히스토리 —
git commit으로 변경이 들어가는.git안의 커밋 데이터베이스.
엄밀히 말하면 저장소 자체는 .git의 내용입니다. 작업 디렉터리는 Git이 히스토리에서 꺼내 펼쳐 놓은 한 버전일 뿐입니다.
git init으로 저장소 만들기
프로젝트 폴더로 이동해서 명령 하나만 실행하면 됩니다.
cd ~/projects/my-app
git init
Initialized empty Git repository in /home/user/projects/my-app/.git/
빈 폴더에서도, 이미 파일이 있는 폴더에서도 저장소를 만들 수 있습니다. 후자의 경우 기존 파일은 그대로 남습니다. git add로 추가하기 전까지 추적되지 않는(untracked) 상태가 될 뿐입니다.
유용한 옵션:
# 폴더를 만들고 그 안에 저장소를 바로 생성
git init my-app
# 첫 브랜치 이름 지정 (지정하지 않으면 master 또는 설정값)
git init -b main
# 앞으로 만드는 모든 저장소의 기본 브랜치를 main으로
git config --global init.defaultBranch main
첫 커밋
커밋이 없는 저장소는 거의 쓸모가 없습니다. git init 직후에는 보통 다음 순서로 진행합니다.
git config --global user.name "Иван Петров"
git config --global user.email "ivan@example.com"
git status
git add .
git commit -m "프로젝트 기본 구조"
이름과 이메일은 컴퓨터에서 한 번만 설정하면 됩니다. 이 값들이 모든 커밋에 기록됩니다. 설정되어 있지 않으면 Git은 커밋을 거부하고 신원을 알려 달라고 합니다.
.gitignore를 바로 추가하세요
첫 git add .를 실행하기 전에 .gitignore를 만드세요. 저장소에 들어가면 안 되는 것들, 예를 들어 의존성, 빌드 결과, 비밀 정보, IDE 파일을 적습니다.
node_modules/
dist/
.env
.idea/
.vscode/
*.log
__pycache__/
이미 커밋된 파일은 .gitignore가 제거하지 않습니다. 파일을 디스크에 남긴 채 추적만 끊어야 합니다: git rm --cached .env를 실행하고 커밋하세요.
.git 폴더 안에는 무엇이 있나
일상 작업에서 이 안을 들여다볼 필요는 없지만, 구조를 알면 많은 질문이 풀립니다.
| 항목 | 저장하는 내용 |
|---|---|
objects/ | 압축된 객체: 파일 내용(blob), 폴더 구조(tree), 커밋 |
refs/heads/ | 브랜치. 마지막 커밋의 해시가 적힌 파일 |
refs/tags/ | 태그 |
HEAD | 현재 브랜치를 가리키는 포인터. 예: ref: refs/heads/main |
config | 이 저장소의 설정. remote 목록 포함 |
index | 인덱스(staging area)의 상태 |
hooks/ | 이벤트(pre-commit, pre-push)에 실행되는 스크립트 |
여기서 중요한 결론이 나옵니다. Git의 브랜치는 해시 하나가 적힌 아주 작은 파일입니다. 그래서 브랜치를 만드는 일은 즉시 끝나며 비용도 들지 않습니다.
폴더가 저장소인지 확인하기
git status
# 또는 더 정확하게
git rev-parse --is-inside-work-tree
저장소 밖에서 실행하면 fatal: not a git repository (or any of the parent directories): .git이 나옵니다. "parent directories"라는 말에 주목하세요. Git은 상위 폴더로 올라가며 .git을 찾습니다. 실수로 홈 디렉터리에서 git init을 실행하면 홈 디렉터리 전체가 저장소가 되므로, 그때는 생긴 .git 폴더를 지워야 합니다.
로컬 저장소와 원격 저장소
git init으로 만든 저장소는 여러분의 컴퓨터에만 있습니다. 코드를 공유하고 백업도 하려면 원격 저장소(remote)를 연결하세요. 서버에 있는 사본으로, GitHub, GitLab, Bitbucket이나 자체 git 서버가 될 수 있습니다.
Git의 관점에서 원격 저장소가 "메인"인 것은 아닙니다. 모든 사본이 완전하며 전체 히스토리를 가집니다. 중심이 되는 것은 팀의 합의일 뿐입니다.
git remote: 원격 저장소 연결하기
remote는 서버 주소에 붙이는 짧은 이름입니다. 관례상 기본 이름은 origin입니다.
# remote 추가
git remote add origin git@github.com:username/my-app.git
# 주소와 함께 목록 보기
git remote -v
origin git@github.com:username/my-app.git (fetch)
origin git@github.com:username/my-app.git (push)
그다음 브랜치를 보내고 원격 브랜치와 연결합니다.
git push -u origin main
git remote 주요 명령
| 명령 | 동작 |
|---|---|
git remote -v | remote 목록과 주소 |
git remote add <이름> <url> | 새 원격 저장소 연결 |
git remote set-url origin <url> | 주소 변경. 예: HTTPS에서 SSH로 |
git remote rename origin old | remote 이름 변경 |
git remote remove old | remote 삭제(서버 자체는 건드리지 않음) |
git remote show origin | 자세한 정보: 브랜치, 추적 상태, 뒤처진 정도 |
주소 형식
https://github.com/user/repo.git— HTTPS. 어디서나 동작하며, 쓰기에는 토큰이 필요;git@github.com:user/repo.git— SSH. 키가 필요하며, 설정 후에는 비밀번호를 묻지 않음;/srv/git/repo.git또는file:///srv/git/repo.git— 로컬 경로. 실험에 편리.
자주 나는 오류
"error: remote origin already exists". 같은 이름의 remote가 이미 있습니다. 주소를 바꾸려면 다시 add하지 말고 git remote set-url origin <url>을 사용하세요.
"failed to push some refs" / "Updates were rejected". 서버에 여러분에게 없는 커밋이 있습니다. 저장소를 웹에서 만들 때 넣은 README가 흔한 원인입니다. git pull --rebase origin main을 실행한 뒤 push를 다시 하세요. 히스토리가 전혀 연결되지 않았다면 Git은 "refusing to merge unrelated histories"라고 답합니다. 그때는 git pull에 --allow-unrelated-histories를 추가해야 합니다. 더 간단한 방법은 사이트에서 빈 저장소를 만드는 것입니다.
"src refspec main does not match any". 아직 존재하지 않는 브랜치를 보내려 하고 있습니다. 커밋이 하나도 없거나, 브랜치 이름이 master인 경우입니다. git branch로 확인하세요.
자체 git 서버: bare 저장소
GitHub가 꼭 필요한 것은 아닙니다. SSH로 접속할 수 있는 어떤 컴퓨터든 원격 저장소가 될 수 있습니다. 그런 서버에는 "빈(bare)" 저장소를 만듭니다. 작업 디렉터리 없이 .git 내용만 있습니다.
# 서버에서
ssh user@server
git init --bare /srv/git/my-app.git
# 내 컴퓨터에서
git remote add origin user@server:/srv/git/my-app.git
git push -u origin main
세 명이 이 서버를 함께 쓰려면, 동료들에게 저장소 폴더에 대한 SSH 접근과 쓰기 권한이 있는 공통 그룹을 주면 됩니다. 브랜치나 프로젝트별로 권한을 나누어야 한다면 그 정도로는 부족하고, 완전한 Git 호스팅이 필요합니다.
bare 저장소에는 "들어가서 파일을 고칠" 수 없습니다. push와 fetch로만 교환하도록 만들어졌습니다. 모든 Git 호스팅 서비스의 저장소도 이런 구조입니다. 웹 인터페이스, 리뷰, 작업 관리가 필요하다면 GitLab, Gitea, Forgejo 같은 자체 호스팅 솔루션을 설치하세요.
로컬 저장소가 서버를 보는 방법: 추적 브랜치
remote를 연결하고 처음 fetch나 push를 하면, origin/main 같은 원격 브랜치가 생깁니다. 이것은 서버의 브랜치가 아니라, 마지막 동기화 때 본 서버 상태의 로컬 스냅샷입니다. fetch, pull, push를 할 때만 갱신됩니다.
그래서 세 가지 교환 명령의 차이가 중요합니다.
| 명령 | 무엇을 바꾸나 |
|---|---|
git fetch | origin/*을 갱신. 내 브랜치와 파일은 건드리지 않음 |
git pull | fetch + origin/main을 현재 브랜치에 병합 |
git push | 내 커밋을 보내고 서버의 브랜치를 갱신 |
내 브랜치가 얼마나 뒤처졌거나 앞서 있는지는 이렇게 확인합니다.
git fetch
git status -sb
## main...origin/main [ahead 2, behind 1]
이 경우 서버에는 없는 내 커밋이 두 개 있고, 내게는 없는 서버 커밋이 한 개 있습니다. push 전에 그 커밋을 먼저 받아야 합니다.
로컬 브랜치와 원격 브랜치의 연결(upstream)은 처음 push할 때 주는 -u 플래그로 정해집니다. 빠뜨렸다면 따로 설정할 수 있습니다: git branch --set-upstream-to=origin/main. 모든 연결은 git branch -vv로 봅니다.
저장소를 몇 개 만들까: 모노레포 또는 프로젝트별 저장소
초보자가 자주 묻는 질문입니다. 저장소는 독립적으로 개발되고 배포되는 단위마다 하나씩 만드세요. 연습 프로젝트, 개인 프로젝트, 독립된 서비스는 각각 별도의 저장소입니다. "내 프로젝트"라는 폴더 하나를 통째로 저장소로 만들지 마세요. 히스토리가 뒤섞이고, 한 프로젝트만 포트폴리오에 올리기 어려워집니다.
대형 회사는 공유 변경과 통합 빌드를 위해 모든 코드를 하나의 모노레포에 두기도 합니다. 하지만 이는 전용 도구가 필요한 의도적인 아키텍처 결정입니다. 초보자는 "프로젝트 하나 = 저장소 하나" 규칙으로 시작하고, 서브모듈 없이 저장소를 다른 저장소 안에 넣지 마세요.
git init과 git clone 중 무엇을 쓸까
| 상황 | 명령 |
|---|---|
| 처음부터 새 프로젝트를 시작 | git init |
| 버전 관리가 없는 코드 폴더가 있음 | 그 폴더에서 git init |
| 프로젝트가 이미 GitHub나 서버에 있음 | git clone <url> |
| 내 서버에 중앙 저장소가 필요함 | git init --bare |
git clone을 쓰면 origin remote가 이미 설정되어 있으므로 직접 추가할 필요가 없습니다.
단계별 예: 폴더에서 GitHub 저장소까지
- 프로젝트 폴더를 만들고
git init -b main을 실행합니다. .gitignore와 README를 추가합니다.- 첫 커밋을 합니다:
git add .와git commit -m "Initial commit". - GitHub에서 빈 저장소를 만듭니다. README, 라이선스, .gitignore는 넣지 않습니다.
- 연결합니다:
git remote add origin <주소>. - 코드를 보냅니다:
git push -u origin main. - 이후에는 같은 순서를 반복합니다. 수정 →
git add→git commit→git push.
정리
Git 저장소는 여러분의 프로젝트에 .git 폴더, 즉 전체 히스토리를 더한 것입니다. git init으로 만들고, git remote add origin과 첫 git push -u로 서버와 연결합니다. 원격 저장소는 GitHub, GitLab 또는 bare 저장소를 둔 자체 서버가 될 수 있습니다. 저장소 생성, 인덱스, remote 연결은 Git 강의에서 실습으로 다룹니다.
자주 묻는 질문
저장소를 지우되 파일은 남기려면 어떻게 하나요?
프로젝트 루트의 숨김 폴더 .git을 지우면 됩니다. Linux와 macOS에서는 rm -rf .git을 씁니다. 파일은 남지만 모든 버전 기록은 사라집니다.
이미 저장소인 폴더에서 git init을 해도 되나요?
네, 안전합니다. Git은 Reinitialized existing Git repository라고 알려 주고 히스토리는 건드리지 않습니다. 빠진 내부 관리 파일만 채워 넣습니다.
한 저장소에 remote를 여러 개 연결할 수 있나요?
얼마든지 가능합니다. 예를 들어 자기 포크용 origin과 원본 프로젝트용 upstream을 두는 방식이 오픈 소스에서 흔합니다.
저장소의 개별 설정은 어디에 있나요?
.git/config 파일에 있습니다. 사용자 전역 설정은 ~/.gitconfig에 있으며, git config --global로 설정합니다.
bare 저장소는 일반 저장소와 무엇이 다른가요?
bare 저장소에는 파일이 펼쳐진 작업 디렉터리가 없고 Git의 내부 데이터만 있습니다. 서버에서 중앙 저장소로 쓰이며, push 대상으로 사용됩니다.