안녕하세요. 알통몬입니다.
오늘은 회사 내부에서 공유했던 깃에 대한 저의 정리 자료를 공유합니다.발표 내용: Git 에 관하여
발표 내용: Git 에 관하여
Git 이란?
깃이 사용하지 않던 시절을 생각해볼까요?
우리는 파일명을 수정하며 버전관리를 했습니다.
20xx.xx.xx-1차.txt
20xx.xx.xx-2차.txt
20xx.xx.xx-최종.txt
20xx.xx.xx-진짜최종.txt
20xx.xx.xx-피드백반영.zip
피드백반영2.zip [김진아, 안호서으 최준채]
…
: 위 방식의 가장 큰 단점은 어떤 것이 최종본인지 알 수 없고,
해당 버전에 어떤게 수정되었는지 제대로 파악하기가 어렵다는 점입니다.
그리고 하나의 파일을 동시에 두명이 수정한 경우는 어떻게 될까요?
마지막에 수정한 사람 것으로 대치됩니다😂
Git 이란 소스코드를 효과적으로 관리하기 위해 개발된 ‘분산형 버전관리 시스템입니다.’
- 최초에는 Linux 소스코드의 관리 목적으로 개발되었습니다.
장점
- 소스코드 변경 이력을 쉽게 확인할 수 있다.
- 특정 시점에 저장된 버전과 비교하거나 특정 시점으로 되돌아갈 수 있다.
- 내가 올리려는 파일이 누군가 편집한 내용과 충돌한다면, 서버에 업로드할 때 경고메시지가 발생된다.
- ⇒ 강제 덮어쓰기를 방지할 수 있다.
원격 저장소와 로컬 저장소
원격 저장소
- 파일이 원격 저장소 전용 서버에 관리되며 여러 사람이 함께 공유하기 위한 저장소
ex) Github, Bitbucket, Gitlab, Atlassian SourceTree 등등
로컬 저장소
- 내 PC에 파일이 저장되는 개인 전용 저장소
Commit
- 파일 및 폴더의 추가/변경 사항을 저장소에 기록하는 행위
- 버그, 수정, 기능 추가 등 특별한 의미가 있는 업데이트를 작업(Issue) 별로 구분하여 각각 커밋하면, 나중에 이력을 보고 특정 변경 내용을 찾기 쉽습니다.
Work Tree
- 깃에서는 우리가 흔히 말하는 폴더를 Work Tree - 작업트리라고 부름.
Index
[A] Index
- Commit 을 실행하기 전의 저장소와 작업 트리 사이에 존재하는 공간을 Index - 인덱스라고 함.
- 커밋은 작업 트리에 있는 변경 내용을 저장소에 바로 기록하는 행위가 아니다.
- 인덱스에 파일 상태를 기록하는 것(stage - 스테이징 한다고 표현하기도 함).
- add 되었지만 commit 되지 않은 공간, 상태라고 생각하면 편하다.
키워드와 명령어 정리
branch
하나의 저장소를 의미한다.
Remote Branch - 원격 저장소 : 깃허브 등에서 생성한 공유하는 저장소
Local Branch - 로컬 저장소 : 개발자가 개별적으로 소유하는 저장소
branch 생성
git branch ooo
// 브랜치가 생성된다.
branch 삭제
git branch -d <branchname>
git branch -d ooo
branch 목록
git branch
branch 이름 변경
git checkout <이름을 변경할 브랜치 이름>
git branch -m <변경할 이름>
git checkout main
git branch -m master
main -> master 로 변경됨.
status
: 현재 branch의 상태를 확인할 수 있다.
- 아무 작업도 하지 않은 상태
- sample.txt 파일을 수정한 상태
- sample.txt 파일을 index에 add한 상태
add
git add ‘aaa.txt’
커밋할 때 필요한 파일 추가(새로 만든, 수정된)
restore
- index에 staging 된(add된) 파일/폴더를 뺀다.
수정내용이 사라지는 것은 아니다.
git restore --staged sample.txt
- 수정내용을 되돌린다.
git restore sample.txt
commit
git commit
add 된 것이나 remove 된 것이 있는 경우에 사용할 수 있다. → 변경사항이 있는 경우
commit 메시지를 추가하고 싶을 경우 -m 키워드를 더하면 된다.
git commit -m “커밋 내용을 입력하면 된다.”
checkout
Branch로 이동한다.
git checkout ooo
브랜치 작성 및 체크아웃을 한꺼번에 하려면 -b 키워드를 사용한다.
git checkout -b<branch>
log
커밋 로그를 볼 때 사용한다.
git log
show
커밋의 상세 내용을 확인한다.
git show <commit>
git show <tagname>
merge
git checkout A
git merge B // B를 A에 병합
git merge A B // B를 A에 병합, A가 B의 내용을 가져온다.
현재 HEAD 에 commit이 넣어진다.
때문에 A 저정소에 B 저장소 내용을 넣으려면
git checkout A저장소 후 git merge B 저장소 하면 된다.
- 변경이력이 모두 남기 때문에 이력이 복잡해진다.
rebase
- 이력은 단순해지지만, 원래의 커밋 이력이 변경된다.
- 정확한 이력을 남겨야할 경우 사용하지 말것.
- 두 개의 공통 Base를 가진 Branch에서 한 Branch의 Base를 다른 Branch의 최신 커밋으로 branch의 base를 옮기는 작업.
git checkout A
git rebase B
하나의 브랜치에 있는 커밋 로그도 합칠 수 있다.
commit1 - commit2 - commit3 - commit4
→ 위 경우 commit3의 변경 이력이 오타 수정이나 특정 값 하나 정도만 수정한 경우라면
commit2와 커밋로그를 합치는 것이 보기 깔끔할 것이다.
이런 경우도 rebase를 활용할 수 있다.
abort
git rebase --abort
rebase 를 취소할 때 사용한다.
continue
git rebase --continue
rebase를 이어서할 때 사용한다.
stash - 임시 저장 정도로 생각하면 편하다.
: 파일의 변경 내용을 일시적으로 기록해두는 영역이다.
현재 작업을 잠시 멈추고 다른 작업을 해야할 때 새롭게 브랜치를 만들고 새롭게 만든 브랜치로 이동하면 작업하던 내용까지 같이 이동하게 되는데, Stash를 사용하면 작업하던 내용을 잠시 두고 새로 만든 브랜치로 이동할 수 있다.
// 변경 내용 임시 저장
git stash // Android Studio에서는 git -> Uncommitted Changes -> stash changes
git stash save
// stash 목록 보기
git stash list
// stash 가져오기
git stash apply // 가장 최근 stash
git stash apply <stash 이름> // 해당 이름의 stash
git stash apply --index // 추후 추가
// stash 자우기
git stash drop // 가장 최근 stash
git stash drop <stash 이름> // 해당 이름의 stash
git stash pop // apply + drop = 가져오고 지우기, List의 removeAt과 비슷
git stash show -p | git apply -R
git stash show -p | <stash 이름> git apply -R //
git stash clear
alias로 편리하게 사용하기
git config --global alias.stash-unapply '!git stash show -p | git apply -R'
git stash apply
#... work work work
git stash-unapply
pull = fetch + merge
git pull <원격 저장소 명> <브랜치 명>
git pull origin master
- 원격 저장소의 변경된 데이터를 가져오고 로컬 저장소와 자동으로 병합해준다.
- 로컬 저장소에도 변경된 데이터가 있는 경우 변경된 데이터를 수동으로 통합하는 작업이 필요하다.
fetch
git fetch
- pull 에서 자동 병합 작업이 제외된다.
- 원격 저장소의 최신 이력을 확인할 수 있다.
- 병합하지 않았기 때문에 이름 없는 브랜치로 로컬에 가져오게 됨.
- ‘FETCH_HEAD’ 라는 이름으로 체크아웃 할 수 있다.
- fetch 후 로컬 저장소와 병합하고 싶을 경우 merge하거나 다시 pull을 실행하면 됨.
push
git push <원격 저장소 명> <브랜치 명>
git push origin master
- 로컬 저장소에서 원격 저장소로 데이터 밀어넣기
Tag
커밋을 참조하기 쉽도록 알기 쉬운 이름을 붙이는 것.
한 번 붙인 태그는 브랜치처럼 위치가 이동하지 않고 고정된다.
- 일반 태그
- 이름만 붙일 수 있음
git tag <tagname>
git log --decorate
- 주석 태그
- 이름을 붙일 수 있음
- 태그에 대한 설명 포함 가능
- 서명 넣을 수 있음
- 태그를 만든 살마의 이름, 이메일과 태그를 만든 날짜 정보도 포함 가능
**git tag -a <tagname>**
- 이 명령어는 입력하고 나면 태그에 대한 설명을 추가하는 화면으로 이동한다.
- 이동한 화면에서 태그에 대한 설명을 추가하고 저장하면 된다.
**git tag -am <“태그에 대한 설명”> <tagname>**
태그 삭제
git tag -d <tagname>
amend
--amend 옵션을 지정하여 커밋을 수행하면 브랜치 상에서 이전에 커밋했던 내용에 새로운 내용을 추가하거나 설명을 수정할 수 있다.
- 누락된 파일을 새로 추가하거나 기존의 파일을 업데이트 해야할 때
- 이전 커밋의 설명을 변경하고 싶을 때
git commit --amend
명령어를 입력하면 편집기가 열리고 커밋 메시지를 수정할 수 있다.
revert
특정 커밋의 내용을 삭제할 수 있다.
rebase -i 나 reset 명령어를 통해서도 커밋을 삭제할 수 있지만, 해당 커밋이 이미 공개상태인 경우에 삭제 작업을 함부로 하기 어렵다. 이런 경우 revert 명령어를 이용해 특정 커밋의 내용을 지우는 새로운 커밋을 만들어 보다 안전하게 처리할 수 있다.
- 이전에 작성한 커밋을 안전하게 지우고 싶을 때
git revert HEAD
reset
더이상 필요 없어진 커밋들을 버릴 수 있다.
명령어를 실행할 때 어떤 모드로 실행할 지 지정하여 ‘HEAD’ 위치와 인덱스, 작업 트리 내용을 함께 되돌릴지 여부를 선택할 수 있다.
모드명 HEAD의 위치 인덱스 작업 트리
soft | 변경함 | 변경 안함 | 변경 안함 |
mixed | 변경함 | 변경함 | 변경 안함 |
hard | 변경함 | 변경함 | 변경함 |
soft: 커밋만 되돌리고 싶을 때
mixed: 변경한 인덱스의 상태를 원래대로 돌리고 싶을 때
hard: 최근의 커밋을 완전히 버리고 이전 상태로 되돌리고 싶을 때
git reset --soft HEAD~~ // ~~ 두개면 2번 째 이전 커밋으로 돌아간다. ~ 한 개면 바로 전 커밋
git reset --mixed HEAD~~
git reset --hard HEAD~~
- reset 전의 커밋은 ‘ORIG_HEAD’ 라는 이름으로 참조할 수 있다.
- 실수로 reset을 한 경우에는 ‘ORIG_HEAD’로 reset 하여 reset 실행 전의 상태로 되돌릴 수 있다.
git reset --hard ORIG_HEAD
cherry pick
다른 브랜치에서 지정한 커밋을 복사해 현재 브랜치로 가져온다.
- 특정 브랜치에 잘못 추가한 커밋을 올바른 브랜치로 옮기려고 할 때
- 다른 브랜치의 커밋을 현재 브랜치에도 추가하고 싶을 때
rebase -i
커밋을 다시 쓰거나 다른 커밋과 바꿔 넣을 수 있다.
특정 위치의 커밋을 삭제하거나 여러 커밋을 하나로 통합하는 작업을 할 수 있다.
- push 하기 전에 이전의 커밋 내용을 정리하고자 할 때
- 그룹으로 묶을 수 있는 커밋들을 알기 쉽게 하나로 통합할 때
- 이전 커밋에 누락된 파일들을 나중에 추가하고자 할 때
- rebase -i 로 커밋 모두 통합하기
git rebase -i HEAD~~ // 현재부터 총 2개
pick 9a54fd4 commit의 설명 추가
#pick 0d4a808 pull의 설명을 추가 -> pick 을 squash 로 변경 후 저장종료
squash 0d4a808 pull의 설명을 추가
# Rebase 326fc9f..0d4a808 onto d286baa
#
# Commands:
# p, pick = use commit
# r, reword = use commit, but edit the commit message
# e, edit = use commit, but stop for amending
# s, squash = use commit, but meld into previous commit
# f, fixup = like "squash", but discard this commit's log message
# x, exec = run command (the rest of the line) using shell
#
# If you remove a line here THAT COMMIT WILL BE LOST.
# However, if you remove everything, the rebase will be aborted.
#
- rebase -i 로 커밋 수정하기
merge --squash
브랜치를 병할할 때 해당 브랜치의 커밋 전체를 통합한 커밋이 추가된다.
- 작업 브랜치 안의 커밋을 한꺼번에 모아서 통합 브랜치에 병합하고자 할 때
issue1의 커밋이 현재 브랜치에 모두 통합된다.
git merge --squash issue1
// 중복되는 파일이 존재하면
git add ***.***
git commit