Git 없는 인터넷 세상이란

git

만약 git이 없는 인터넷 세상이라면 소프트웨어 개발과 인터넷 서비스는 현재보다 매우 퇴보되었을 것이다. 그저 리눅스를 개발하던 리눅스 토발즈와 리눅스팀은 사용하던 비트키퍼가 무상 서비스를 종료하여 직접 git을 개발하게 된게 인터넷 세상에서 없어서는 안되는 존재로 될 줄은 자신도 몰랐을 것이다.

git이 없던 이전에는 하나의 서버에 존재하는 코드를 수정하던 ’중앙집중식 시스템’에서 각자의 컴퓨터에서 코드를 수정하고 병합하는 ’탈중앙화 시스템’을 통해서 소프트웨어 개발할 때 문제의 원인을 찾고 이전 상태로 되돌리기 쉽게 하여 코드의 안정성과 품질을 향상시키고, 서버 운영 및 배포 분야에서도 git을 사용하여 인프라 설정을 코드로 관리하고, 변경 이력을 추적하며, 배포를 자동화할 수 있게 되었다.

그렇다면 github는 도대체 무엇일까?




Git 이랑 Github랑 다른거야?

git and github

git은 분산 버전 관리 시스템이다. 소스 코드 변경 이력을 추적하고 관리하며 언제든지 이전 버전의 코드로 되돌리거나 특정 시점의 변경된 코드를 확인할 수 있게 해준다.

github는 git 저장소를 호스팅하는 웹 기반 서비스이다. git으로 관리되는 프로젝트를 온라인에서 저장하고 공유할 수 있는 플랫폼이며, 인터넷만 작동한다면 프로젝트 코드를 공유하고 협업할 수 있도록 도와준다.

표로 설명하자면 이렇게 된다.

gitgithub
소프트웨어서비스
CLIGUI
로컬 시스템으로 작동웹 기반, 온라인으로 작동
LinuxMicrosoft
분산 버전 관리git repo 호스팅

한마디로 실제 작업은 git 으로 하고 git을 작업한 것들을 시각적으로 확인하고 git으로 할 수 있는 작업을 웹을 통해서 할 수 있게 해주는게 github인 것이다.

git 이 없다면 github도 없다.




사용법

how to use git command

github 를 통해 직접 할 수 있지만 웹과 에디터를 돌아가며 확인하는 것은 비효율적이므로 에디터에 터미널을 열고 작업하는게 효율적이다. 이제부터 git 자주 사용하는 명령어를 알아보도록 하자.

초기 설정 및 워크플로우

로컬에 git과 github를 연결하는 초기 설정은 다음과 같다. 참고로 github와 gitlab 둘 다 사용한다면 점에 있어서 말해주겠다.

// git 설치
sudo pacman -S git        // Arch Linux
sudo apt install git      // Ubuntu
sudo dnf install git      // Fedora
winget install Git.Git    // Windows
choco install git         // Chocolatey
brew install git          // Mac

// git 전역 사용자 정보 설정
git config --global user.name "Your Name"
git config --global user.email "your@email.com"

// 사용자 확인
git config --global user.name
git config --global user.email
// git 설치
sudo pacman -S git        // Arch Linux
sudo apt install git      // Ubuntu
sudo dnf install git      // Fedora
winget install Git.Git    // Windows
choco install git         // Chocolatey
brew install git          // Mac

// git 전역 사용자 정보 설정
git config --global user.name "Your Name"
git config --global user.email "your@email.com"

// 사용자 확인
git config --global user.name
git config --global user.email
// ssh 키 생성
ssh-keygen -t ed25519 -C "yourgithub@email.com"
ssh-keygen -t ed25519 -C "yourgitlab@email.com" -f ~/.ssh/id_ed25519_gitlab

// ssh 설정 파일 생성 및 권한 설정
touch ~/.ssh/config
chmod 600 ~/.ssh/config

// ssh config 파일 생성 및 편집
Host github.com               // Github 설정 (기존)
    HostName github.com
    User git
    IdentityFile ~/.ssh/id_ed25519       // 기존 github 키
    IdentitiesOnly yes
       
Host gitlab.com               // Gitlab 설정 (새로 추가)
    HostName gitlab.com
    User git
    IdentityFile ~/.ssh/id_ed25519_gitlab // 새 gitlab 키
    IdentitiesOnly yes

// ssh 에이전트에 키 추가
eval "$(ssh-agent -s)"

// 두개의 키 모두 추가
ssh-add ~/.ssh/id_ed25519         // github 키
ssh-add ~/.ssh/id_ed25519_gitlab  // gitlab 키

// 추가된 키 확인
ssh-add -l

// 키 내용 확인
cat ~/.ssh/id_ed25519.pub
cat ~/.ssh/id_ed25519_gitlab.pub
// ssh 키 생성
ssh-keygen -t ed25519 -C "yourgithub@email.com"
ssh-keygen -t ed25519 -C "yourgitlab@email.com" -f ~/.ssh/id_ed25519_gitlab

// ssh 설정 파일 생성 및 권한 설정
touch ~/.ssh/config
chmod 600 ~/.ssh/config

// ssh config 파일 생성 및 편집
Host github.com               // Github 설정 (기존)
    HostName github.com
    User git
    IdentityFile ~/.ssh/id_ed25519       // 기존 github 키
    IdentitiesOnly yes
       
Host gitlab.com               // Gitlab 설정 (새로 추가)
    HostName gitlab.com
    User git
    IdentityFile ~/.ssh/id_ed25519_gitlab // 새 gitlab 키
    IdentitiesOnly yes

// ssh 에이전트에 키 추가
eval "$(ssh-agent -s)"

// 두개의 키 모두 추가
ssh-add ~/.ssh/id_ed25519         // github 키
ssh-add ~/.ssh/id_ed25519_gitlab  // gitlab 키

// 추가된 키 확인
ssh-add -l

// 키 내용 확인
cat ~/.ssh/id_ed25519.pub
cat ~/.ssh/id_ed25519_gitlab.pub

이후 자신의 ssh 키를 github/gitlab에 등록하면 된다. 등록은 해당 사이트에 접속하여 등록하면 되고, ssh 연결이 제대로 작동하는지 테스트 해보면 된다.

// 연결 확인
ssh -T git@github.com
ssh -T git@gitlab.com

// result
"Hi <your-github-username>! You've successfully authenticated..."  // github
"Welcome to GitLab, @<your-gitlab-username>!"                      // gitlab
// 연결 확인
ssh -T git@github.com
ssh -T git@gitlab.com

// result
"Hi <your-github-username>! You've successfully authenticated..."  // github
"Welcome to GitLab, @<your-gitlab-username>!"                      // gitlab

이로써 github(gitlab)이 내 컴퓨터와 연결된 것이다. 그럼 이제 내 프로젝트를 어떻게 github에 연결할 수 있는지 확인하자.

// cli를 통해서 github에 repo를 만들고자 한다면 설치
sudo pacman -S github-cli        // Arch Linux
winget install GitHub.cli        // Windows
choco install github-cli         // Chocolatey
brew install gh                  // Mac
// cli를 통해서 github에 repo를 만들고자 한다면 설치
sudo pacman -S github-cli        // Arch Linux
winget install GitHub.cli        // Windows
choco install github-cli         // Chocolatey
brew install gh                  // Mac
// Ubuntu, Debian
(type -p wget >/dev/null || (sudo apt update && sudo apt install wget -y)) \
&& sudo mkdir -p -m 755 /etc/apt/keyrings \
&& out=$(mktemp) && wget -nv -O$out https://cli.github.com/packages/githubcli-archive-keyring.gpg \
&& cat $out | sudo tee /etc/apt/keyrings/githubcli-archive-keyring.gpg > /dev/null \
&& sudo chmod go+r /etc/apt/keyrings/githubcli-archive-keyring.gpg \
&& sudo mkdir -p -m 755 /etc/apt/sources.list.d \
&& echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main" | sudo tee /etc/apt/sources.list.d/github-cli.list > /dev/null \
&& sudo apt update \
&& sudo apt install gh -y
	

// Fedora, CentOS, Red Hat (DNF4)
sudo dnf install 'dnf-command(config-manager)'
sudo dnf config-manager --add-repo https://cli.github.com/packages/rpm/gh-cli.repo
sudo dnf install gh --repo gh-cli
// Ubuntu, Debian
(type -p wget >/dev/null || (sudo apt update && sudo apt install wget -y)) \
&& sudo mkdir -p -m 755 /etc/apt/keyrings \
&& out=$(mktemp) && wget -nv -O$out https://cli.github.com/packages/githubcli-archive-keyring.gpg \
&& cat $out | sudo tee /etc/apt/keyrings/githubcli-archive-keyring.gpg > /dev/null \
&& sudo chmod go+r /etc/apt/keyrings/githubcli-archive-keyring.gpg \
&& sudo mkdir -p -m 755 /etc/apt/sources.list.d \
&& echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main" | sudo tee /etc/apt/sources.list.d/github-cli.list > /dev/null \
&& sudo apt update \
&& sudo apt install gh -y
	

// Fedora, CentOS, Red Hat (DNF4)
sudo dnf install 'dnf-command(config-manager)'
sudo dnf config-manager --add-repo https://cli.github.com/packages/rpm/gh-cli.repo
sudo dnf install gh --repo gh-cli

이로써 git 과 github를 위한 내 컴퓨터 설정을 전부 마쳤다. 다음으로 git 과 gh 명령어를 통해 repo를 만들고 원격 저장소에 업로드 하는 플로우 까지 확인해 보겠다.

// 프로젝트 초기 설정
git init

// 현재 파일 스테이징 영역에 추가하기
git add .

// 추가한 파일에 대한 설명 추가 및 로컬 저장소에 HEAD 포인터와 업데이트
git commit -m "init"

// 상태 확인
git status

// 만약 branch 이름이 master 인데 main 으로 변경하고 싶으면
git branch -m master main

// 다시 확인
git status

// github repo 만들기 (github cli 설치 필요 / 비공개, 현재 디렉토리 소스 사용, 원격 저장소 설정)
gh repo create repo-name --private --source=. --remote=origin

// 원격 저장소에 추가
git push -u origin main

// 다음부터는 간결하게
git add .
git commit -m "fixed: type error"
git push
// 프로젝트 초기 설정
git init

// 현재 파일 스테이징 영역에 추가하기
git add .

// 추가한 파일에 대한 설명 추가 및 로컬 저장소에 HEAD 포인터와 업데이트
git commit -m "init"

// 상태 확인
git status

// 만약 branch 이름이 master 인데 main 으로 변경하고 싶으면
git branch -m master main

// 다시 확인
git status

// github repo 만들기 (github cli 설치 필요 / 비공개, 현재 디렉토리 소스 사용, 원격 저장소 설정)
gh repo create repo-name --private --source=. --remote=origin

// 원격 저장소에 추가
git push -u origin main

// 다음부터는 간결하게
git add .
git commit -m "fixed: type error"
git push

reset 과 revert

만약 업로드한 코드가 다른 팀원들에게 오해의 소지가 있을 수 있거나 혹은 코드 수정에 있어서 부족하다 싶으면 다시 돌아가야 된다. 그런 경우에도 다음과 같은 명령어로 작업할 수 있다.

첫번째로 그냥 히스토리 없이 완전 리셋 하는 방법이다. 이는

// 바로 이전으로 돌아가기 위해
git reset --hard HEAD~1

// 이후 수정된 코드를 push하는 법
git push --force origin <branch-name>

// 혹은 협업자가 아직 업데이트 하지 않았을 경우 (권장)
git push --force-with-lease origin <branch-name>
// 바로 이전으로 돌아가기 위해
git reset --hard HEAD~1

// 이후 수정된 코드를 push하는 법
git push --force origin <branch-name>

// 혹은 협업자가 아직 업데이트 하지 않았을 경우 (권장)
git push --force-with-lease origin <branch-name>

추가로 --hard를 사용했는데 세 가지의 모드가 있으니 확인해보자

// HEAD 포인터만 이동 (스테이징 영역에 그대로 유지)
git reset --soft <commit-hash>

// HEAD 포인터와 스테이징 영역을 이동 (기본값)
git reset --mixed <commit-hash>

// HEAD 포인터, 스테이징 영역, 작업 디렉토리 모두 이동
git reset --hard <commit-hash>
// HEAD 포인터만 이동 (스테이징 영역에 그대로 유지)
git reset --soft <commit-hash>

// HEAD 포인터와 스테이징 영역을 이동 (기본값)
git reset --mixed <commit-hash>

// HEAD 포인터, 스테이징 영역, 작업 디렉토리 모두 이동
git reset --hard <commit-hash>

두번째로 히스토리는 보존하지만 변경 사항들을 취화는 새로운 커밋을 생성 하는 방법이다. 참고로 되돌리는게 아닌 커밋을 생성한다는 점에 주목해야한다. 대부분 revert 가 오로지 ’되돌리는 명령어’로 생각하고 있는데, 실제로는 되돌리지만 새로운 커밋으로 만들어서 수정하고 다시 커밋하는 것이다.

// 가장 최근 커밋 변경 취소 후 새로운 커밋 생성
git revert HEAD

// 특정 커밋 변경 취소 후 새로운 커밋 생성
git revert <commit-hash>
// 가장 최근 커밋 변경 취소 후 새로운 커밋 생성
git revert HEAD

// 특정 커밋 변경 취소 후 새로운 커밋 생성
git revert <commit-hash>

고로 reset은 “로컬에서 없던 일“로 만들 때 사용하고, revert는 “이미 공유된 변경사항을 취소하고 새로운 작업으로 기록“할 때 사용한다. 참고로 git reset --hard는 복구가 안되므로 신중하게 사용하여야 한다.

checkout 과 branch

checkout과 branch 명령어를 많이 햇갈려 하는데 쉽게 말해서 checkout은 현재 작업하는 환경을 전환하는데에 사용하고 branch는 생성, 목록 확인, 삭제등 브랜치 자체를 관리하는 명령어이다.

// 로컬 브랜치 확인
git branch

// result
* main
dev
fix-login-function

// 모든 브랜치 확인
git branch -a

// result
* main
dev
fix-login-function
remotes/origin/fix-login-function
remotes/origin/fix-mobile-layout
remotes/origin/user-profile

// 새로운 브랜치 생성
git branch admin-dashboard

// 브랜치 삭제
git branch -d new-login
// 로컬 브랜치 확인
git branch

// result
* main
dev
fix-login-function

// 모든 브랜치 확인
git branch -a

// result
* main
dev
fix-login-function
remotes/origin/fix-login-function
remotes/origin/fix-mobile-layout
remotes/origin/user-profile

// 새로운 브랜치 생성
git branch admin-dashboard

// 브랜치 삭제
git branch -d new-login
// dev 로 작엄장소 변경
git checkout dev

// 브랜치를 생성함과 동시에 이동하기
git checkout -b payment
// dev 로 작엄장소 변경
git checkout dev

// 브랜치를 생성함과 동시에 이동하기
git checkout -b payment

tag

만약 자신의 프로젝트를 버전별로 관리하고 싶다면 태그를 생성하면 된다.

// 변경사항 커밋 및 푸시
git add .
git commit -m "release v0.1.0"
git push

// 현재 커밋에 태그 붙이고 생성
git tag v0.1.0

// 태그를 github에 푸시
git push origin v0.1.0
// 변경사항 커밋 및 푸시
git add .
git commit -m "release v0.1.0"
git push

// 현재 커밋에 태그 붙이고 생성
git tag v0.1.0

// 태그를 github에 푸시
git push origin v0.1.0

이후 나중에 기능 추가 혹은 수정을 하고난 후 다시 배포해야될 일이 생긴다면 새로운 태그를 생성하고 다시 푸시하면 된다.

// 0.1.0 -> 0.1.1

// 변경사항 커밋
git add .
git commit -m "release v0.1.1"

// 새 태그 생성
git tag v0.1.1

// push
git push origin v0.1.1
git push origin main
// 0.1.0 -> 0.1.1

// 변경사항 커밋
git add .
git commit -m "release v0.1.1"

// 새 태그 생성
git tag v0.1.1

// push
git push origin v0.1.1
git push origin main

태그 관리도 알아놓으면 유용하니 참고하자.

// 목록 확인
git tag

// 특정 태그로 체크아웃
git checkout v0.1.0

// 태그 삭제 (local)
git tag -d v0.1.0

// 태그 삭제 (github)
git push origin --delete v0.1.0

// 태그에 메시지 추가 (선택)
git tag -a v0.1.0 -m "Release v0.1.0: Initial release"
git push origin v0.1.0
// 목록 확인
git tag

// 특정 태그로 체크아웃
git checkout v0.1.0

// 태그 삭제 (local)
git tag -d v0.1.0

// 태그 삭제 (github)
git push origin --delete v0.1.0

// 태그에 메시지 추가 (선택)
git tag -a v0.1.0 -m "Release v0.1.0: Initial release"
git push origin v0.1.0

remote

또한 remote에 대해서도 헷갈릴 수 있는데 이 명령어는 자신의 컴퓨터(로컬) git 저장소와는 별개로, 네트워크 상에 존재하는 git 저장소의 복사본이다. 한마디로 회사 git 코드를 공유하고 함께 작업할 때 회사 git 저장소와 내 컴퓨터 git 저장소의 중간 허브 역할을 한다.

이로인해 만약 내 컴퓨터에서 문제가 생기더라도 원격 저장소는 데이터 손실을 방지할 수 있고, 인터넷만 연결되어 있다면 프로젝트 코드에 접근하고 수정할 수 있다.

생소하다고 생각할 수 있지만 모두 사용하는 명령어들이니 확인해보자.

// 원격 저장소를 로컬 저장소에 연결할 때
git remote add origin <repo>

// 원격 저장소를 로컬에 통째로 복사할 때
git clone <repo>

// 로컬 저장소에 커밋한 것들을 원격 저장소로 업로드 할 때
git push origin main

// 로컬 저장소에 커밋된 것들을 원격 저장소에서 가져올 때
git pull origin main

// 원격 저장소의 변경사항들을 로컬로 가져오지만 현재 작업중인 브랜치와 병합하지 않을 때
git fetch origin
// 원격 저장소를 로컬 저장소에 연결할 때
git remote add origin <repo>

// 원격 저장소를 로컬에 통째로 복사할 때
git clone <repo>

// 로컬 저장소에 커밋한 것들을 원격 저장소로 업로드 할 때
git push origin main

// 로컬 저장소에 커밋된 것들을 원격 저장소에서 가져올 때
git pull origin main

// 원격 저장소의 변경사항들을 로컬로 가져오지만 현재 작업중인 브랜치와 병합하지 않을 때
git fetch origin




마치며

torvalds in Korea

Linux 와 Git을 개발한 Linus Benedict Torvalds

너무 길어지게 되서 gh 명령어도 많이 있지만 기본적인 repo 생성만 작성하였고, diff, marge도 있는데 포스트에는 제외했다.

솔직히 설명한 명령어들 전부 외울 필요는 없다. 사용하다보면 저절로 익히게 되고, 만약 원하는 기능이 기억이 안난다 하면 그때 검색해서 해도 큰 문제는 없다. 하지만 ssh 를 두개 관리하는거나 헷갈리는 부분에 명확한 설명을 찾아본다면 시간이 지체되기 때문에 이 포스트로 git을 이용하는 개발자들에게 도움이 되었으면 한다.

마지막으로 이 글을 읽는 사람들은 제발 시중에 있는 git, github 관련된 책이나 강의는 구매하지 말고 직접 찾아보도록 하자.