Git과 GitHub
우리가 개발한 서비스의 규모가 커지면 그에 따른 코드의 양도 방대해지고, 추가와 수정 혹은 변경과 같은 작업들이 계속 이루어지게 된다.
이러한 작업들을 형상관리라고 하는데 Git이라는 것은 형상관리를 쉽게 할 수 있게 도와주는 프로그램이다.
우리가 위의 사진과 같이 프로젝트를 진행했다면 어땠을까?
어떤 것이 최종 결과물인지 모르고, 또 내가 필요한 코드가 어디에 있는지 모른다. (실제 경험담이 있음...)
만약 Git을 사용했으면 하나의 폴더 안에서 계속 작업물의 버전을 높여가면서 작업을 할 수 있을 것이다. Git을 사용해서 작업이 끝나면 그것을 GitHub에 공유하여 여러 사람들이 볼 수 있게 할 수 있고, 또한 동료들과의 협업도 가능하다.
Git과 GitHub의 특징들
Git은 소프트웨어 개발 중 소스 코드의 변경 사항을 추적하기 위한 분산 버전 제어 시스템(VCS)이다. 개발자 간의 작업 조정을 위해 설계되었지만, 모든 파일 세트의 변경 사항을 추적할 때도 사용한다.
GitHub는 Git의 모든 분산 계정 제어 및 소스 코드 관리(SCM) 기능을 제공하는 웹 기반 Git 저장소 호스팅 서비스이다.
Git과 GitHub의 차이점을 더 살펴보면 아래의 표와 같다.
번호 | Git | GitHub |
1 | Git은 소프트웨어(프로그램)다. | GitHub는 서비스이다. |
2 | Git은 CLI를 지원한다. | GitHub는 GUI를 지원한다. |
3 | Git 프로그램은 로컬에 설치된다. | GitHub는 웹에서 호스팅된다. |
4 | Git은 Linux에서 관리한다. | GitHub는 마이크로소프트에서 관리한다. |
5 | Git은 버전 제어 및 코드 공유에 중점을 둔다. | GitHub는 중앙 집중식 소스 코드 호스팅에 중점을 둔다. |
6 | Git은 소스코드 이력을 관리하는 버전 관리 시스템이다. | GitHub는 Git 저장소를 위한 호스팅 서비스이다. |
7 | Git에는 사용자 관리 기능이 없다. | GitHub에는 사용자 관리 기능이 내장되어 있다. |
Git 명령어
Git 명령어를 알아보기 전에 일단 우리가 먼저 이해해야되는 것은 Staging 영역과 로컬 Repo 영역을 알아야 한다.
그림을 살펴보면 먼저 내 PC에 있는 작업 폴더에서 작업 파일들을 스테이징 영역에 먼저 이동시키고, 그다음 commit이란 명령어를 통해서 로컬 영역으로 이동하게 된다.
로컬 영역에서만 있다면 다른 사람들은 해당 작업물에 접근할 수 없게 되는데 push 명령어를 사용하여 GitHub에 작업물을 올려야 접근이 가능하게 된다.
참고로 위에서 언급한 차이점에서도 나왔지만 Git은 리눅스에서 개발했기 때문에 기존의 리눅스 명령어를 알고 있거나 익숙한 사람은 조금 더 친숙하게 사용할 수 있다. (리눅스의 여러 명령어와 옵션을 사용할 수 있음)
이제 명령어를 하나씩 살펴보자
git init(저장소 생성)
init 명령어를 통해서 하나의 로컬 저장소를 생성한다.
저장소를 새롭게 생성하게 되면 해당 작업 폴더에는 .git이라는 숨김 폴더가 생성되는데 해당 폴더가 하나의 로컬 저장소를 의미한다.
우리가 개발한 결과물을 GitHub에 올리게 되면 .git이라는 저장소를 공유하게 되는 것이다.
Git을 사용할 때 주의할 점으로는 내 저장소 상태를 확인하고 공유를 해야지 무턱대고 공유하면 안 된다.
git config (설정 확인)
git config 명령어는 Git의 사용 환경을 설정 혹은 변경을 해주는 명령어이다.
git config(계정 생성)
git config --global user.name "사용자_이름"
git config --global user.email [사용자_이메일]
commit 작업을 위해서는 가장 먼저 해야 할 일 중에 하나로 사용자 이름과 이메일 주소를 설정해줘야 하는데 commit 할 때마다 해당 정보를 사용하기 때문에 한 번 commit 한 이후에는 사용자 정보를 변경할 수 없게 된다. 따라서 처음에 설정을 할 때 유의해서 작성하거나 혹은 --global 옵션을 빼서 프로젝트마다 다른 이름과 이메일 주소를 사용하는 방법도 있다.
git config(commit 템플릿 적용)
git config 글로벌 설정으로 commit 템플릿을 적용할 수 있는데 미리 작성한 양식으로 commit 메세지를 바로 작성할 수 있게 설정할 수 있다.
git status(상태 확인)
git status 명령어는 로컬 영역과 스테이징 영역의 상태를 표시해주는 명령어이다.
먼저 test_first라는 텍스트 파일을 만들고 상태를 확인해보면
해당 사진과 같이 Untracked files에 파일이 있는 것을 확인할 수 있다.
새로 생성한 파일을 추가하고 난 후 상태를 확인해 보면 new file이라고 친절하게 표시해 준다. 만약 파일을 수정했다면 midified라고 표시해 주는 것을 알 수 있다.
git add(스테이징 영역으로 파일 추가)
git add 명령어는 파일을 스테이징 영역으로 추가해 준다.
git은 상태를 계속 추적하면서 스테이징 영역으로 추가되었다는 것을 표시해 준다.
하나씩 파일을 add 하는 것이 번거롭다면 add 뒤에 "."을 붙여서 모든 파일을 한꺼번에 스테이징 영역으로 추가할 수 있다.
git rm(파일을 삭제)
git rm [--cached] [-r] [-n] [-f | --force] [--ignore-unmatch] .....
Git에서 파일을 삭제하고 싶을 때 rm 명령어를 통해서 Tracked 상태의 파일을 제거하여 Untraced 상태로 만들 수 있다.
현재 예시에서 사용한 --cached 옵션은 스테이징 영역에 추가된 파일을 다시 그 전의 영역으로 돌려놓는다.
rm을 사용할 때 주의해야 할 점은 파일을 삭제하고 나서 삭제했다는 내역 자체를 commit 해줘야 된다는 점이다.
git commit(로컬 영역으로 추가)
commit 명령어는 아마도 Git을 쓰면 가장 많이 사용하게 될 명령어이지 않을까 생각한다.
commit 명령어를 통해서 스테이징 영역에 있는 파일들을 로컬 영역으로 추가해 준다. 개발자가 사용하게 될 GitHub에는 이 commit으로 로컬 영역에 추가된 파일들을 원격 저장소에 올리게 된다.
commit을 하고 난 이후 상태를 확인해 보면 스테이징 영역에는 아무 파일도 없는 것을 확인할 수 있다.
git commit --amend(덮어쓰기)
commit 명령어의 옵션 중에서 --amend 옵션은 아직 푸시되지 않은 상태에서 최신 commit 메시지를 바꾸고 싶을 때 사용하는 명령어 옵션이다. 위의 사진과 같이 init_v2라는 commit 메시지에서 덮어쓰기로 바꾼 것을 확인할 수 있다.
git reset(리셋)
git reset 명령어는 이전 commit으로 되돌리는 명령어이다. 주로 이전 commit으로 돌아가고 싶거나 혹은 master 브랜치로 릴리즈를 했는데 치명적인 버그로 인하여 롤백이 필요한 경우에 이전 commit으로 되돌아가기 위해서 사용한다.
reset 명령어에는 3가지의 옵션이 존재한다.
--hard: 돌아간 commit 이후의 변경 이력은 모두 삭제된다.
--mixed: 변경 이력은 모두 삭제하지만 변경 내용은 남아있는다.
--soft: 변경 이력은 모두 삭제하지만 변경 내용은 남아있다. (스테이징 영역으로 가서 바로 commit이 가능함)
git checkout(해당 commit으로 돌아가기)
git checkout 명령어는 내가 지정한 commit으로 돌아가는 명령어이다.
checkout 명령어는 나중에 브랜치를 배우면 자주 사용하게 될 명령어이다.
checkout 명령어를 사용할 때 한 가지 주의할 점은 HEAD를 통해서 해당 commit으로 돌아온 것이지 나머지 커밋 내용들이 삭제되는 것은 아니다.
git remote(저장소 업로드)
git 작업 완료되면 GitHub 원격 저장소로 업로드할 수 있다. 먼저 GitHub에서 새로운 원격 저장소를 생성한 후 주소를 복사하여 현재 내 PC 로컬 저장소와 연결하고 push 명령어를 통해서 파일들을 업로드하게 된다.
git branch(브랜치 생성 및 확인)
git branch 명령어로 새로운 브랜치를 생성할 수 있다.
그럼 branch라는 것은 뭘까?
브랜치란 분기 작업을 수행할 때 사용하는 명령어로 원본 파일의 복사본을 만들어 새로운 기능을 개발하고, 테스트를 진행해 볼 수 있다. 브랜치를 통해 개발을 진행하면 원본 파일에 영향을 주지 않아 안전하게 새로운 기능을 추가해 볼 수 있어서 많이 사용되는 명령어이다.
브랜치를 새로 생성하고 -al 옵션을 통해서 현재 어떤 브랜치가 있는지 확인할 수 있다. (참고로 master도 하나의 브랜치이다.)
git checkout(브랜치로 이동)
이전에 생성한 브랜치로 이동하려면 checkout 명령어를 사용해야 한다.
checkout 명령어는 이전에 설명했던 것처럼 내가 지정한 커밋으로 이동하는 기능도 있지만, 내가 생성한 브랜치로 이동할 수도 있다.
git log --graph --all(브랜치 확인)
내가 생성한 브랜치와 기존의 master 브랜치의 작업 흐름을 확인하고 싶을 때는 git log를 사용하는데 이때 --graph --all 옵션을 추가하면 조금 더 직관적으로 확인할 수 있다.
git merge(브랜치 병합)
이제 새로 생성한 브렌치에서 기능을 추가해 보고 테스트까지 완료했다면 기존의 원본 파일과 병합하는 과정을 거쳐야 한다. 이때 사용하는 명령어가 git merge 명령어이다.
내가 작성한 파일들을 옮길 위치로 먼저 이동하고 난 뒤에 옮길 대상이 있는 브랜치를 merge 대상으로 작성하여 병합을 진행하게 된다.
혹시라도 원본 파일과 병합할 때 충돌이 발생하면 위의 사진과 같이 어느 부분에서 충돌이 발생했는지 친절히 알려준다.
충돌이 일어난 파일을 확인하여 조금 더 효율적인 코드를 선택하게 되고 선택에서 제외된 브랜치 내용을 제거한 후 다시 add와 commit 과정을 거쳐서 병합을 진행한다.
지금까지 설명했던 방법은 merge의 방법 중 3-way merge라는 방법으로 이것 외에 2가지 방법이 더 있다.
Fast-forward merge(페스트 포워드 머지)
Fast-forward merge는 기존의 브랜치를 버리고 새로운 브랜치만 commit 하는 방식이다.
기준이 되는 master(main) 브랜치에 신규 commit이 없으면 자동으로 Fast-forward merge가 된다.
Rebase merge(리베이스 머지)
Rebase merge는 브랜치의 시작점을 다른 commit으로 옮기는 것이다.
3-way merge가 아닌 강제로 Fast-forward merge를 하고 싶을 경우 사용하게 된다.
하지만 Rebase merge를 사용할 경우 충돌이 자주 발생할 수 있다는 단점이 존재한다.
참고 자료