일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | ||
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 |
- 코드잇
- Git
- 중간이들
- 데이터베이스시스템
- HTML
- 파이썬프로그래밍기초
- Cookie
- redis
- presignedurl
- 유노코딩
- 코딩테스트
- CSS
- node.js
- 꿀단집
- SQL
- Python
- 항해99
- 코딩테스트준비
- JavaScript
- 프로그래머스
- TiL
- 파이썬
- MySQL
- 엘리스sw트랙
- 방송대
- nestjs
- 99클럽
- aws
- 개발자취업
- 방송대컴퓨터과학과
- Today
- Total
배꼽파지 않도록 잘 개발해요
[코드잇] Git 본문
◆ Git 써보기
◆ GitHub 시작하기
◆ 커밋 다루기
◆ 브랜치 사용하기
◆ Git 협업하기
◆ Git 자유자재로 활용하기
◆ Git 써보기
버전 관리 : 파일의 변화를 시간에 따라서 기록했다가 나중에 특정 시점에 버전을 다시 꺼내올 수 있는 시스템
버전 관리의 장점
- 지난 과정 확인 기능
- 잘못된 부분이 생기면 이전 버전으로 돌아갈 수 있음.
레포지토리(repository)
- 커밋이 저장되는 곳
- git을 쓰면 프로젝트 안에 .git이라는 디렉토리가 만들어짐.
이 .git이 레포지토리임.
→ 프로젝트의 변경사항이 저장되어 있는 .git 디렉토리가 레포지토리임.
커밋(commit)
- 프로젝트 디렉토리의 특정 모습을 하나의 버전으로 남기는 행위 & 결과물
- 프로젝트 디렉토리의 모습을 하나의 버전으로 남기는 동작
커밋을 하면 커밋하는 당시의 프로젝트 디렉토리의 모습이 마치 사진처럼 레포지토리에 저장됨.
고정된 결과물 자체도 커밋이라고 함.
첫 커밋 해보기
MathTool 디렉토리가 프로젝트 디렉토리가 됨.
Git으로 MathTool 디렉토리의 버전 관리를 시작함.
git init
Initialized empty Git repository in C:/Users/airyt/MathTool/.git/
비어있는 레포지토리 생성
레포지토리 : 프로젝트 디렉토리의 각 버전이 담기는 저장소
git 내부에 있는 것들은 다음과 같음.
git은 프로젝트 디렉토리에 버전 관리를 하기 위해서 자신만의 규칙을 가지고 복잡한 작업을 처리함.
MathTool 디렉토리 안에 calculator.py 파일 작성해주기
파일 생성하는 방법
nano calculator.py
안에 내용 작성후 Ctrl + X 누르고 파일명 입력하고 Y 눌러서 저장하기
MathTool 디렉토리 안에 License 파일도 하나 생성해준다.
숨겨진 파일 및 세부 정보를 포함하여 현재 디렉토리에 있는 모든 파일 및 하위 디렉터리 표시
ls -al
- 첫 커밋을 하기 전에 꼭 해야할 것
→ Git에게 내가 누군지 알려줘야함.
커밋을 할 때는 그 커밋을 누가 했는지도 반드시 함께 기록해야 함. - commit에 필요한 것 :
이름, 이메일, 커밋에 대한 정보
- add된게 하나도 없고 untracked 상태인 파일들이 존재한다는 문구가 보임.
- untracked : 깃에 의해 아직 추적되지 않고 있다.
아직 Git으로 뭔가를 해준 적이 없어서 파일이 버전 관리 대상이 아닐 때 이런 상태를 untracked라고 함. - 커밋을 하기 전에는 커밋할 파일들을 미리 지정해줘야 함.
파일을 새로 생성하거나 원래 있던 파일의 내용들을 수정하고 나면 그 파일들은 그 새로운 모습으로 커밋에 포함될 거라고 지정을 하는 것임.
이런 사전 작업을 add라고 함. - add : 방금 말한 대로 어떤 파일의 수정된 모습을 커밋에 반영할거다는 의미
git add calculator.py
git add License
git commit -m "Create calculator.py and License"
이 출력 결과는 커밋이 되었다는 뜻이고 그 결과를 보여주는 것임.
- root-commit : 이 커밋이 프로젝트의 첫 번째 커밋이라는 뜻임.
- 7 insertions : 7줄이 추가됨.
commit에 관한 주의사항
- 처음으로 커밋을 하기 전 사용자의 이름과 이메일주소를 설정
- 커밋 메시지 남기기 (옵션 -m)
커밋을 할 때는 반드시 그 커밋에 관한 정보를 담고 있는 메시지를 남겨줘야 함. - 커밋할 파일을 git add로 지정해주기
Git의 3가지 작업 영역
Git은 내부적으로 크게 3가지 종류의 작업 영역을 두고 동작함.
→ working directory, staging area, repository
working directory (working tree) |
· 작업을 하는 디렉토리 |
staging area (index) |
· git add를 한 파일들이 존재하는 영역 · 커밋을 하게 되면 staging area에 있는 파일들만 커밋에 반영됨. |
repository | · 변경 이력들이 저장되어 있는 영역 |
반영되는 순서
- working directory에서 뭔가 작업을 하고,
- 작업한 파일들을 git add 해주고,
- 커밋을 하면 staging area에 있던 파일들의 모습이 마치 영화의 한 장면, 스냅샷처럼 이 repository에 저장됨.
staging area의 필요성
- 여러 파일을 수정했더라도 두 파일 모두 그 최신 모습을 다음 커밋에 반영하고 싶지 않을 수도 있음.
- 만약 staging area가 없다면 원하는 것들만 선별적으로 커밋에 반영할 수 없게 됨.
git add 더 자세히 알아보기
방금 2개의 파일을 수정함.
하지만 일부러 파일 1개만 git add를 해보겠음.
git add calculator.py
방금 calculator 파일과 License 파일 두 개를 수정했지만 git add는 calculator 파일만 해줬음.
지금 calculator.py 파일만 staging area에 새로운 모습으로 있어서
calculator는 주석이 추가된 새로운 모습으로, License는 주석이 추가되기 이전 모습 그대로 커밋에 반영될 것임.
git status 명령어 입력
- status : 깃이 인식하고 있는 프로젝트 디렉토리의 현재 상태를 보여줌.
- 커밋을 하기 전에 git status를 해서 staging area에 수정한 파일들이 다 들어있는지 확인하면 좋음.
git status
디렉토리를 git add 해주면 디렉토리 안에 있는 모든 파일이 staging area에 추가됨.
변경사항이 있는 모든 파일을 한번에 staging area에 추가하기
'.'의 의미 : 현재 프로젝트 디렉토리 내에서 변경사항이 생긴 모든 파일들을 staging area에 추가하라
git add .
Git이 보는 파일의 4가지 상태
git으로 관리되는 파일은 일종의 '상태(status)'라는 것을 가진다는 사실임.
파일들이 가지는 상태
- Untracked 상태
- Tracked 상태 : Staged, Unmodified, Modified
Untracked 상태 | · 파일이 Git에 의해서 그 변동사항이 전혀 추적되지 않고 있는 상태 · 파일을 새로 생성하고 그 파일을 한번도 git add 해주지 않았다면 이 상태임. |
|
Tracked 상태 | · 파일이 Git에 의해 그 변동사항이 추적되고 있는 상태 | |
Staged 상태 | · 파일의 내용이 수정되고 나서, staging area에 올라와있는 상태 · 새로 생성한 파일에 내용을 쓰고 git add를 해주거나 한번이라도 커밋에 포함됐었던 파일이라도 내용을 수정하고 git add를 해주면 이 상태임. |
|
Unmodified 상태 | · 현재 파일의 내용이 최신 커밋의 모습과 비교했을 때 전혀 바뀐 게 없는 상태. · 커밋을 하고 난 직후에는 working directory 안의 모든 파일이 이 상태가 됨. |
|
Modified 상태 | · 최신 커밋의 모습과 비교했을 때 조금이라도 바뀐 내용이 있는 상태. |
git add 취소하기
- git add : staging area에 파일 추가
- git reset : staging area에서 파일 제거
→ 변경된 새 모습은 그대로 working directory에 남아있음.
staging area에서 제거되었다고 해도 calculator.py는 여전히 sayHello 함수가 추가된 모습 그대로 working directory에 남아 있음.
clean : 이전 커밋 이후로 변경사항 없음.
특정 git 커맨드의 사용법을 알고 싶다면
커맨드의 의미나 사용법을 자세히 알고 싶을 경우
git help
git help
git help add
man git-
man git-
man git-add
◆ GitHub 시작하기
Local Repository의 내용을 Remote Repository로 보내기
• 원격 레포지토리(리모트 레포지토리) : 깃허브의 레포지토리
• 내 컴퓨터의 레포지토리 : 로컬 레포지토리
→ Math_Box(리모트)는 MathTool(로컬)의 복제본 레포지토리임.
Git bash에서 복사 붙여넣기
- 복사하기 : Ctrl + Insert
- 붙여넣기 : Shift + Insert
로컬 레포지토리와 똑같은 레포지토리를 깃헙 저장소에 생성함.
Local Repository에서 바뀐 내용을 Remote Repository에도 반영하기
로컬 저장소에서 새로운 파일을 생성하였음.
방금한 새로운 커밋도 리모트 레포지토리로 보내려면 따로 작업을 해줘야 됨.
→ git push 명령어를 사용하면 됨.
로컬 레포지토리의 내용을 리모트 레포지토리에 반영한다는 명령어
git push
깃허브는 파일 이름이 README인 경우 내용을 바로 보여줌.
로컬 레포지토리에서 새로운 커밋을 할 때마다 그것들도 매번 'git push'라는 명령어를 통해 리모트 레포지토리에 반영해줘야함.
Remote Repository에서 바뀐 내용을 Local Repository에도 반영하기
GitHub에서도 직접 커밋을 할 수 있음.
이렇게 되면 리모트 레포지토리에 새로운 커밋이 추가되었음.
내 컴퓨터에 있는 로컬 레포지토리의 내용이 뒤처져있는 상태임.
리모트 레포지토리에 새로운 커밋을 로컬 레포지토리에 가져오려면 git pull이라는 커맨드를 쓰면 됨.
리모트 레포지토리의 새로운 내용을 가져와서 자신의 로컬 레포지토리에 반영시킨다는 의미
git pull
로컬 레포지토리와 똑같은 내용의 리모트 레포지토리를 만든다는 것은 크게 두 가지 의미를 가짐.
- 안전성 : 똑같은 레포지토리가 하나 더 생기는 거니까 안전해짐.
- 협업 가능 : 다른 개발자가 리모트 레포지토리 내용을 본인 컴퓨터에서 가져와서 작업할 수 있음.
아무나 git push를 할 수 있는게 아니다
- 원칙적으로 자신의 리모트 레포지토리에는 자신만 git push를 할 수 있음.
- 만약 다른 사용자도 git push를 할 수 있게 해주려면 그 사용자를 해당 리모트 레포지토리의 collaborator로 지정하면 됨.
다른 프로젝트 가져오기
https://github.com/numpy/numpy
GitHub - numpy/numpy: The fundamental package for scientific computing with Python.
The fundamental package for scientific computing with Python. - numpy/numpy
github.com
현재 MathTool 폴더 안에 있음.
여기에 numpy 레포지토리를 가져오면 두 프로젝트가 엉켜버림.
→ 일단 다른 곳으로 이동해야함.
부모 디렉토리로 이동한다.
그 다음 리모트 레포지토리를 가져올 수 있는 커맨드를 치면 됨.
깃허브 프로젝트의 레포지토리를 그대로 복제
git clone
numpy 레포지토리가 내 컴퓨터에 복사됨.
오픈 소스 프로젝트
오픈 소스 프로젝트(open source project)
- 소스 코드가 공개되어 있는 프로젝트
- 1983년 ‘리차드 스톨만(Richard Stallman)’이라고 하는 MIT의 연구원이 '자유 소프트웨어 운동'을 시작하면서 활성화됨.
- 이 영향을 받은 대표적인 프로그램이 바로 'GNU 리눅스'라고 하는 운영체제임.
- 오픈 소스라고 해도 라이센스는 각각 다르므로, 잘 확인해야 함.
장점 | · 무료로 사용할 수 있다. · 여러 개발자들이 참여하기 때문에 폐쇄적으로 코드를 관리할 때보다 코드의 신뢰도가 더 높다. (이 부분은 사람마다 의견이 다를 수 있음.) · 오픈 소스 프로젝트에 참여 중인 다른 개발자들에게 질문을 할 수 있다. · 어떤 프로그램을 개발할 때 특정 분야에서 사실상 표준처럼 사용되는 오픈 소스 프로그램을 많이 활용할수록 전체 개발 속도를 단축시킬 수 있다. |
단점 | · 참여자 수가 많지 않거나, 참여자의 실력이 좋지 않으면 소스 코드의 신뢰성을 보장하기 어렵다. · 해당 오픈 소스를 사용해서 문제가 생겼을 때 보상을 해주거나, 책임을 질 주체가 없다. |
◆ 커밋 다루기
커밋 히스토리 살펴보기
커밋 아이디 (커밋 해시)
git은 각각의 커밋을 구별하기 위해 각 커밋에 아이디를 붙여서 관리함.
커밋 히스토리 살펴보는 명령어
git log
q 눌러서 나가면 됨.
커밋 아이디와 커밋 메시지만 한줄씩 보여주는 명령어
git log --pretty=oneline
pretty 앞에 하이픈 두 개 써야됨.
이 옵션의 값으로 oneline을 주면 되고, online은 커밋당 한 줄씩 출력하라는 뜻임.
커밋 내용 자세히 확인하기
git show (커밋아이디 4자리)
커밋 아이디를 전부 입력하면 힘듦.
앞에 4자리만 쳐도 알아서 인식함.
실행을 하면 해당 커밋과 바로 그 이전의 커밋의 차이점을 보여줌.
m 옵션 없이도 커밋 메시지 남기기
git commit 명령어만 입력하면 다음과 같이 뜸.
git add .
git commit
'#'으로 시작하는 내용은 커밋 메시지에 반영되지 않음.
이건 Git에서 기본 설정된 텍스트 에디터가 실행된 창임.
- i : 입력모드
- ESC → :wq →Enter : 커밋 메시지 저장 후 자동 커밋
-m옵션 없이 git commit만으로 텍스트 에디터에 커밋 메시지 남기기의 장점 :
복잡하고 긴 커밋 메시지를 쉽게 남길 수 있음.
최신 커밋 수정하기
커밋을 수정하고 싶은 경우에 수정하고 다시 커밋을 하게 되면 불필요한 커밋이 하나 더 생김.
최신 커밋만 다시 수정할 것임.
해당 코드 수정하고 나서 아래와 같이 명령어 입력
git add .
git commit --amend
입력하면 이렇게 편집창이 뜨고 'i'를 눌러서 입력모드로 들어가면 됨.
이렇게 하면 최신 커밋이 수정이 됨.
이전의 최신 커밋 아이디와 현재 최신 커밋 아이디가 바뀜.
커밋 생성, 커밋 메시지 작성 가이드라인
커밋 정보
- 커밋을 한 사용자 아이디
- 커밋을 한 날짜, 시간
- 커밋 메시지
커밋 메시지 작성 가이드라인
- 커밋 메시지의 제목과 상세설명 사이에는 한 줄을 비워두기
- 커밋 메시지의 제목 뒤에 온점(.)을 붙이지 마라
- 커밋 메시지의 제목의 첫 번째 알파벳은 대문자로 작성
- 커밋 메시지 제목은 명령조로 작성 (Fix it)
- 커밋의 상세 내용
- 왜 커밋을 했는지
- 어떤 문제가 있었는지
- 적용한 해결책이 어떤 효과를 가지는지
커밋할 때 알아야 할 가이드라인
- 하나의 커밋에는 하나의 수정사항, 하나의 이슈를 해결한 내용만 남겨라.
최대한 작은 단위의 변화를 기준으로 커밋을 하라. - 실행했을 때 에러가 발생하지 않을 코드만 커밋해라.
긴 커맨드에 alias 설정하기
명령어를 aliasing하기
git config alias.history 'log --pretty=oneline'
앞으로 git histroy라고만 써도 자동으로 git log --pretty=oneline을 실행함.
두 커밋 간 차이 보기
커밋 A와 커밋 B의 차이를 보고 싶을 때가 있음.
비교하고 싶은 커밋 아이디 두 개를 써주면 됨.
좀 더 이전의 커밋 아이디를 먼저 써주면 됨.
git diff dba6 ea6e
이전 커밋으로 git reset하기
HEAD의 의미
- HEAD : 어떤 커밋 하나를 가리킴
보통 가장 최근에 한 커밋을 가리킴
매번 더 새로운 커밋을 가리킴 - working directory / working tree 내부는 HEAD가 가리키는 커밋에 따라 다르게 구성됨.
git reset
- 과거 커밋으로 아예 돌아가게 함.
- HEAD가 과거의 커밋을 가리키게 할 수 있음.
- working directory의 내용도 과거 커밋의 모습으로 돌아가게 함.
reset 명령어로 되돌리기
git reset --hard ea6e
해당 커밋 때의 상태로 파일이 되돌아감.
참고로 staging area에 있던 것들은 커밋을 하더라도 그것과 상관없이 계속 남아있음.
git reset의 세 가지 옵션
옵션에 따라 어떤 작업 영역들이 리셋되는지 달라짐.
git reset [옵션] eea5 | working directory | staging area | repository |
--soft | 안 바뀜 | 안 바뀜 | HEAD가 eea5 커밋을 가리킴 |
--mixed | 안 바뀜 (가장 최근에 작업했던 모습 그대로) |
eea5 커밋처럼 바뀜 | HEAD가 eea5 커밋을 가리킴 |
--hard | eea5 커밋처럼 바뀜 (커밋 이후 작업들이 전부 사라짐) |
eea5 커밋처럼 바뀜 | HEAD가 eea5 커밋을 가리킴. |
divide 함수 추가 후 git add . 실행
이후 git reset --soft를 입력하였는데 워킹 디렉토리에는 영향이 없고, 스테이징 영역도 그대로임.
Staging area에 README는 왜 있는것일까?
→ 이전 커밋과 README 파일도 차이가 있어서 modified 상태가 됨.
git reset --mixed를 입력함.
working directory는 그대로이고, staging area는 리셋으로 인해 해당 HEAD로 바뀜.
- Unstaged changes after reset : staging area에 있던 최신 파일들이 reset 때문에 staging area에서 내려왔다
현재 작업내용이 이전으로 돌아가서 내용이 좀 날아간 상태임.
이럴 때는 GitHub에 올려뒀던 Remote Repository를 사용하면 됨.
git pull 작업 중에 원격 저장소에서 들어오는 파일이 작업 디렉토리의 README.md 파일을 덮어쓰게 된다는 것을 나타냄.
# 변경 사항 보관하기
# -u 또는 --include-untracked 옵션 : untracted 파일도 숨기도록 지시
git stash -u
# 원격 저장소에서 최신 변경 사항 가져오기
git pull
# 숨겨진 변경사항 다시 적용
git stash pop
HEAD를 기준으로 git reset하기
- HEAD^ : 현재 HEAD가 가리키고 있는 커밋의 바로 이전 커밋
git reset --hard HEAD^
- HEAD~2 : 현재 HEAD가 가리키고 있는 커밋보다 2단계 이전의 커밋
git reset --hard HEAD~2
일반적인 리셋 명령어
git reset [옵션] [커밋 아이디]
• git reset을 한다고 그 이후의 커밋이 사라지는 것은 아니다.
• git reset은 과거의 커밋뿐만 아니라 현재 HEAD가 가리키는 커밋 이후의 커밋으로도 할 수 있다.
커밋에 tag 달기
커밋에 태그 달기
git tag [태그 이름] [커밋 아이디]
프로젝트 디렉토리에 있는 모든 태그 조회
git tag
각 태그와 연결된 커밋 확인
git show [태그 이름]
◆ 브랜치 사용하기
브랜치란
- branch : 하나의 코드 관리 흐름
- On branch master : 마스터 브랜치 위에 있다
- master (main) : 레포지토리를 만들고 커밋을 하면 자동으로 생기는 브랜치
브랜치 생성
git branch premium
이때까지 작업한 내용들도 모두 프리미엄 브랜치에 속함.
만든 브랜치로 이동
git checkout preminum
작업을 하고 커밋을 하면 premium branch에만 반영됨.
그리고 그 커밋들은 이제 master branch랑 아무 상관 없게 됨.
브랜치 다뤄보기
현재 브랜치 확인
git branch
브랜치 삭제
git branch -d test
브랜치 생성과 동시에 그 branch로 바로 이동
git checkout -b test
브랜치 merge하기
merge : 다른 브랜치에서 했던 커밋을 가져오고 싶을 때 사용
- 무료버전 : master 브랜치
- 유료버전 : premium 브랜치
- 현재 master 브랜치에서 계산기에 기능을 추가하였음.
이걸 premium 브랜치에도 그대로 반영하고 싶을 때 어떻게 해야될까?
→ branch merge를 하면 됨.
현재 위치인 premium branch에 master branch를 합치겠다
git merge master
merge할 때 conflict 발생
현재 상황
- master 브랜치 : calculator.py 파일의 divide 함수 이름이 "divide_premium"
- premium 브랜치 : calculator.py 파일의 divide 함수 이름이 "divide_free"
Merge conflict in calculator.py
똑같은 divide 함수를 premium 브랜치와 master 브랜치에서 다르게 수정하였음.
구분선을 기준으로 위와 아래 내용이 다름.
이 상황에서 merge를 하면 git은 둘 중 어떤 것을 반영해야하는지 모름.
일단 다 지우고 새로쓴다.
git add .와 git commit을 입력하였음.
conflict를 해결하고 커밋하면 이런식으로 커밋메시지가 자동으로 설정됨.
Conflict 해결방법
- 수정하기
1) 컨플릭트가 발생한 파일을 연다
2) 머지의 결과가 되었으면 하는 모습대로 코드를 수정한다 - conflict가 났을 때 merge 자체를 취소하기
- 상황 : conflict가 발생한 파일들이 너무 많아서 conflict를 최소화할 수 있는 방식으로 파일들을 수정하고 커밋하고 싶을 때, 나중에 머지하고 싶을 때
- 명령어 : git merge --abort
merge를 취소하기
git merge --abort
여러 파일에서 conflict가 났을 때
- 파일 하나씩 conflict를 해결하고 git add [파일 이름] 커맨드로 하나씩 staging area에 올리거나
(중간중간에 git status 커맨드로 현재 상태 확인하면서) - 모든 파일들의 conflict를 다 해결하고, git add . 커맨드로 한번에 staging area에 올리고
커밋을 하면 됨.
Remote Repository의 브랜치
• master : 로컬 레포지토리의 master 브랜치
• origin/master : 리모트 레포지토리의 master 브랜치
현재 로컬 레포지토리에 있는 master브랜치 내용을 origin이라는 리모트 레포지토리로 보낸다는 뜻
- --set-upstream(-u)옵션 : 로컬 레포지토리에 있는 브랜치가 origin에 있는 브랜치를 tracking(추적)하는 걸로 설정
git push -u origin master
만약 이러한 tracking connection이 설정되지 않고 git push, git pull을 쓰면 자동으로 실행이 안됨.
git push origin master:master
이렇게 직접 적어줘야됨.
- 앞의 master : 로컬 master
- 뒤의 master : 원격 master
master 브랜치와 premium 브랜치 둘다 push하기
리모트 레포지토리의 master 브랜치가 로컬 레포지토리의 master 브랜치보다 항상 이전 커밋에 머물러 있음.
git push를 하면 이때까지의 커밋들이 전부 리모트 레포지토리의 master브랜치로 올라갈 것임.
두 브랜치가 같은 커밋에 놓여짐.
원격 저장소의 master 브랜치도 최신 내용을 가지고 있는 것임.
프리미엄 브랜치도 마찬가지로 설정해주기
프리미엄 브랜치로 이동해서 git push를 입력하니까 upstream branch가 없다는 내용이 출력됨.
리모트 레포지토리에도 premium branch가 생김.
HEAD와 브랜치의 관계
- 브랜치(branch) : 커밋을 가리키는 존재(포인터)
- HEAD : 브랜치를 통해 커밋을 간접적으로 가리키는 존재(포인터)
HEAD는 직접적으로 브랜치를 가리키고 있음.
만약 현재 브랜치에서 premium 브랜치로 checkout을 하면 git HEAD가 premium 브랜치를 가리키게 됨.
머지 커밋 (A + B)이 생성됨.
머지(merge) : 헤드가 가리키던 커밋에 다른 브랜치가 가리키던 커밋을 합쳐서 새로운 커밋을 만드는 작업
git reset과 git checkout의 차이점
git checkout의 의미
git checkout master
master 브랜치로 이동하라
= HEAD가 master 브랜치를 가리키도록 하라
→ HEAD가 master 브랜치가 가리키던 커밋을 간접적으로 가리키게 됨
HEAD가 특정 커밋을 직접 가리키게 하는 이유
→ 과거의 특정 커밋에서 새로운 브랜치를 만들고 싶을 때
1) 세 번째 커밋인 9033으로 이동
git checkout 9033
여긴 브랜치가 없으므로 HEAD가 직접 커밋을 가리킴
2) 이 상태에서 새로운 브랜치를 생성함.
git branch premium
이러면 HEAD와 premium브랜치가 각각 직접 커밋을 가리키게 됨.
3) HEAD가 브랜치를 가리키도록 설정
git checkout premium
이렇게 되면 HEAD가 premium 브랜치를 가리키고, premium 브랜치가 커밋을 가리키게 되는 원래 상태가 됨.
1 | 2 | 3 |
git checkout 9033 | git branch premium | git checkout premium |
![]() |
![]() |
![]() |
reset과 checkout 비교
git reset | git checkout |
HEAD가 가리키던 브랜치가 다른 커밋을 가리키도록 함. | HEAD 자체가 다른 커밋이나 브랜치를 가리키도록 함. |
HEAD도 결국 간접적으로 다른 커밋을 가리키게 됨. | 브랜치를 통하지 않고, 커밋을 직접적으로 가리키는 HEAD를 Detached head라고 함. |
새로운 커밋을 만들지 않는 merge
- Fast-forward 머지 : 새로운 커밋이 생기는 게 아니라 단지 브랜치가 이동하게 되는 머지
- 3-way 머지 :
- base때의 내용과 비교했을 때 달라진 부분이 있는 것이 우선시되고,
- 두 브랜치에서 둘다 변화가 일어났을 때는 Conflict를 발생시켜서 사용자가 스스로 선택하게끔 한다
◆ Git 협업하기
git push 전에 git pull을 해야하는 경우가 많을 겁니다
- git push : 로컬 레포지토리에 있는 branch 내용을 리모트 레포지토리의 branch로 보내는 것
- git pull : 리모트 레포지토리에 있는 branch 내용을 로컬 레포지토리로 받아오는 것
- git push -f : pull을 안 해도 강제로 푸시가 가능함. (개인 프로젝트에서만 사용할 것)
로컬에서 Premium 브랜치로 이동 → License 파일 수정함.
현재 상황
- 한 프로그램을 각각 다른 개발자가 다른 방식으로 개발한 것임.
- 리모트 레포지토리에서 작업하다보면 이런 일이 많음.
이 상태에서 로컬 레포지토리에서 git push를 하면 어떻게 될까?
이미 다른 개발자가 추가한 내용이 있는데, 내껄 반영하면 덮어쓰기가 될 수 있음.
로컬 레포지토리를 수정하였는데 리모트 레포지토리에 변화가 있으면 일단 git pull을 해야함.
→ 다른 개발자가 작업한 내용이 나의 premium branch에도 반영됨.
그래서 git pull을 했는데 merge conflict가 떴음.
git pull을 하면 리모트 레포지토리의 premium 브랜치에 있는 최신 커밋들을 로컬 레포지토리의 premium 브랜치로 가져옴. 그리고 그것을 그대로 merge함.
리모트 레포지토리의 최신 커밋까지 가져와서 merge 하는 과정까지가 git pull임.
그래서 git pull을 할 때도 conflict가 발생할 수 있음.
결론 : git pull은 결국 리모트 레포지토리의 branch를 가져와서 merge하는 동작임.
리모트 레포지토리를 가져와서 각각 새로운 커밋을 한 상황임.
개발자 B가 먼저 git push를 하였음.
개발자 A는 바로 git push를 할 수 없음.
git pull을 이용해서 리모트 레포지토리의 그 브랜치에 있는 다른 개발자가 한 커밋을 자신의 로컬 레포지토리에 있는 브랜치에도 반영시켜야 함.
이 과정은 결국 리모트 레포지토리의 브랜치를 가져와서 내 로컬 레포지토리에 merge 하는 것과 같음.
대부분의 경우 git pull을 하면 충돌이 남.
→ conflict를 해결해주고 다시 커밋을 하면 됨.
→ git push를 하면 됨.
git fetch
• git pull : 리모트 레포지토리의 브랜치를 검토할 필요없이 바로 합치고 싶을 때 (fetch + merge)
• git fetch : 리모트 레포지토리의 브랜치를 검토해야할 때
git fetch
- merge는 하지 않고 가져오기만 해주는 명령
- 리모트 레포지토리에 있는 브랜치 내용을 일단 가져와서 살펴본 후에 머지하고 싶을 때 사용
- 리모트 레포지토리에 있는 브랜치의 내용과 내가 작성한 코드를 비교해서 잘못된 부분이 없는지 검토해야할 때
리모트 레포지토리의 브랜치에 문제가 있을 때 해결방법
1) 잘못된 코드를 추가한 개발자에게 함수를 지우고, 다시 리포트 레포지토리에 올려달라고 하기
2) 잘못된 부분을 알아서 해결하고 다시 git push 하기
이 코드는 누가 작성했을까?
한 가지 파일이 완성되기 전까지 어떤 커밋들이 있어왔는지를 볼 수 있는 커맨드
- git blame
프로그램에 문제가 발생했을 때 어떤 파일에 특정 코드를 누가 작성했는지 찾아내기 위한 커맨드
- git show (커밋 아이디)
Author가 나와서 누가 작성했는지 알 수 있음.
이미 Remote Repository에 올라간 커밋을 취소해야 한다면
calculator.py 파일에 squre 함수를 추가하고 리모트 레포지토리에 커밋 푸시를 한 상황임.
이미 올라간 커밋을 취소하고 싶으면 어떻게 해야할까?
- git revert (커밋 아이디)
최신 커밋에서 한 작업을 되돌리고 다시 커밋을 해주는 커맨드
revert를 하면 해당 커밋에서 했던 작업을 거꾸로 되돌리고 그걸 다시 되돌리게 됨.
작성했던 squre 함수가 사라졌음.
여러 커밋 취소하기
더 과거의 커밋을 대상으로, 여러 개의 커밋을 대상으로 한번에 revert 하는 것도 가능함.
주의할 점 :
- 이렇게 쓰면 facd 커밋은 포함되지 않음.
- facd 커밋 바로 다음부터 eea5까지의 커밋이 해당되는 것임.
main 브랜치와 premium 브랜치에서 리드미 파일을 초기화해줬음.
◆ Git 자유자재로 활용하기
git reset을 하고 나서 돌아오려면?
이때까지 한 커밋들은 사라진 것일까?
→ reset을 해도 reset한 커밋 이후의 커밋들이 삭제되는 것은 아님.
예전에 했던 커밋으로 되돌리면 다시 예전의 커밋들이 전부 다 잘 보임.
git reset을 하더라도 커밋들이 삭제되는 것은 아님.
헤드가 가리키던 branch가 새로운 커밋을 가리키게 될뿐임.
지금 같은 경우는 커밋 log에서 이전 커밋의 아이디를 찾아내서 적을 수 있었지만, 만약 커밋 히스토리를 출력하지 않고 그냥 git reset을 했다면 어떻게 할까?
git reflog
- 커밋 아이디를 확인할 수 있음.
- HEAD가 가리켰던 commit들의 id 확인하기
git reset --hard 4497
혹은 git reset HEAD@{1}
커밋 히스토리를 보는 다양한 방법
모든 브랜치에 있는 히스토리 출력하기
git log --pretty=oneline --all
--graph
커밋 히스토리가 각 브랜치와의 관계가 잘 드러나도록 그래프 형식으로 출력
git log --pretty=oneline --all --graph
깔끔한 커밋 히스토리를 원할 땐 git merge 대신 git rebase
현재 premium 브랜치에 있는데 실험용 브랜치를 더 만들 것임.
premium 브랜치의 복잡한 함수를 만들 때에는 추가하기 전에 이 실험용 branch에서 실험을 하고 나서 premium 브랜치에 추가할 것임.
test branch에서 추가했던 get_Median 함수를 premium branch에 추가해도 된다는 결정
premium 브랜치에서 test branch로 merge하면 됨.
premium 브랜치 : get_Remainder
test 브랜치 : get_Median
현재 premium 브랜치에서 test브랜치를 merge한 상황임.
에디터로 충돌을 해결해준다.
그래프 로그 출력으로 머지가 잘 되었음을 확인
방금처럼 git merge를 하지 않고 git rebase를 하는 방법도 있음.
머지하기 전 커밋으로 되돌림.
rebase : 베이스를 다시 지정하다, 커밋을 재배치한다
- git rebase test (현재 프리미엄 브랜치에 있음)
프리미엄 브랜치의 베이스를 테스트 브랜치로 재지정
- git rebase --continue
컨플릭트가 발생해서 제대로 진행되지 못한 리베이스를 계속 진행하라
rebase를 하면 새로운 커밋이 발생하는게 아니라
Add get_Median function 커밋을 거쳐온 것처럼 커밋 히스토리의 구조 자체가 바뀜.
rebase라는 말의 뜻 그대로 test branch가 가리키는 커밋을 premium branch가 자신의 새로운 베이스로 만드는 것임.
merge와 rebase의 차이점
1) rebase는 새로운 커밋을 만들지 않는다.
2) rebase로 만들어진 커밋 히스토리는 merge로 만들어진 커밋 히스토리보다 좀 더 깔끔함.
→ 결과물은 둘 다 같음.
작업 내용 임시 저장하기
코드를 수정하고 있는데 당장 무료 버전의 라이센스 정보를 수정해달라는 요청이 들어왔음.
빨리 main 브랜치로 가서 작업을 해야될 것 같음.
하던 작업을 저장하고 터미널로 이동함.
main 브랜치로 이동하려는데 오류가 났음.
지금 바로 다른 브랜치로 가버리면 방금까지 작업한 내용이 날아갈 수도 있다는 뜻임.
지금 main 브랜치로 체크아웃을 하면 main 브랜치를 통해 새로운 커밋을 가리키게 됨. 그럼 워킹 디렉토리 내부도 그 커밋의 내용대로 바뀌게 됨.
방금 내가 작업한 내용이 모두 사라질 수 있기 때문에 이런 에러가 뜨는 것임.
git stash
stash : 안전한 곳에 보관하다, 넣어두다
working directory에서 작업하던 내용을 깃이 따로 보관함.
보관하는 장소를 stack이라고 함.
stack : 어떤 데이터를 저장하는 구조
먼저 넣은 것이 가장 나중에 꺼내짐.
git stash를 하면 가장 먼저 저장한 내용이 가장 나중에 꺼내짐.
git stash를 통해 작업 내용을 스택에 저장하고, git stash list를 통해 저장내역을 확인함.
git stash
- 어떤 브랜치에서 하던 작업을 아직 커밋하지 않았는데 다른 브랜치로 가야하는 상황에서 작업 중이던 내용을 잠깐 저장하고 싶을 때
- 최근 커밋 이후로 작업했던 내용은 모두 스택에 옮겨지고 working directory 내부는 다시 최근 커밋의 상태로 초기화
- 작업한 내용은 어차피 스택에 있기 때문에 걱정하지 않아도 됨.
다시 main 브랜치로 이동해서 요청대로 License 파일을 수정하였음.
git stash apply
- 스택에 있는 내용을 다시 working directory로 가져와서 적용
이 상태에서 calculator.py 불러와서 이어서 작업하면 됨.
파일 열어보면 그대로 남아있음.
잘못된 브랜치에서 작업하고 있었다면?
git stash를 쓰는 다른 상황?
→ 잘못된 브랜치에서 작업했을 때
현재 get_Percent 함수는 프리미엄 브랜치에서 해야할 작업을 마스터 브랜치에서 한 상황임.
git stash에서 적용한 내용은 꼭 같은 branch에서만 적용할 수 있는 건 아님.
git stash list를 입력하면 다른 브랜치에서 했던 작업 내용도 나옴.
git stash apply를 하면 conflict가 뜸.
충돌 해결하려고 에디터로 들어감.
원래 premium 브랜치에 있던 calculator.py 내용과 방금 작업했던 내용 사이에 충돌이 생겨서 그런 것임.
수정하고 add, commit을 해준다.
잘못된 브랜치에서 작업하는 실수를 했을 땐?
1. git stash로 stack에 작업 내용을 저장한다
2. 올바른 브랜치로 가서 다시 git stash apply를 한다
이미 적용한 작업 내용은 지워주는게 좋음.
스택에서 작업한 내용 삭제해주기
git stash drop (삭제하고 싶은 작업내용 ID)
git stash drop stash@{0}
git stash 명령어 모음
1. 작업 내용 저장
git stash
2. 작업 내용 조회(=스택 살펴보기)
git stash list
3. 작업 내용 적용
git stash apply [작업 내용의 아이디]
작업 내용의 아이디를 생략하면 가장 최근의 작업 내용이 적용됨
4. 작업 내용 제거
git stash drop [작업 내용의 아이디]
작업 내용의 아이디를 생략하면 가장 최근의 작업 내용이 제거됨
5. 작업 내용을 적용하면서 동시에 스택에서 제거
git stash pop [작업 내용의 아이디]
필요한 커밋만 가져오는 git cherry-pick
1부터 숫자 n까지 합을 구해주는 get_Sum 함수를 프리미엄 버전에 추가
가장 좋은 방법을 찾기 위해 테스트를 진행
테스트를 위해 test 브랜치로 이동
커밋을 완료했는데 누군가가 새로운 방법으로 구현된 get_Sum 함수를 만들었다고 해서 그걸 적용해보기로 했음.
get_Sum_ver2 함수를 만들어서 커밋함.
버전1의 getSum 함수만 가져오면 될듯.
버전 1 함수를 만들었던 부분만 가져오고 싶음.
0f26 커밋에서 했던 작업만 그대로 가져오고 싶음.
- git cherry-pick
자신이 원하는 작업이 들어있는 커밋들만 가져와서 현재 브랜치에 추가함.
충돌 해결하고 다시 add commit을 해준다.
여러 커밋을 하나의 커밋으로 만들기
팩토리얼 함수를 추가해줬음.
프로그래밍을 하다가 더 효율적인 팩토리얼 함수를 찾게됨.
맨 처음 팩토리얼함수를 추가하고 했던 커밋은 지금와서 보면 필요없는 커밋임.
그냥 이 커밋을 없었던 걸로 하고 싶은데 어떻게 해야될까?
없애고 싶은 자잘한 커밋 이전으로 git reset을 하는데 이때 --soft나 --mixed 옵션을 붙여서 쓰면 됨.
과거의 커밋으로 reset이 되면서도 현재 워킹 디렉토리의 모습은 보존이 됨.
HEAD는 이전 커밋을 가리키지만 working directory는 그대로임.
◆ 커맨드 정리
git init | 현재 디렉토리를 Git이 관리하는 프로젝트 디렉토리(=working directory)로 설정하고 그 안에 레포지토리(.git 디렉토리) 생성 |
git config user.name 'codeit' | 현재 사용자의 아이디를 'codeit'으로 설정(커밋할 때 필요한 정보) |
git config user.email 'teacher@codeit.kr' | 현재 사용자의 이메일 주소를 'teacher@codeit.kr'로 설정(커밋할 때 필요한 정보) |
git add [파일 이름] | 수정사항이 있는 특정 파일을 staging area에 올리기 |
git add [디렉토리명] | 해당 디렉토리 내에서 수정사항이 있는 모든 파일들을 staging area에 올리기 |
git reset [파일 이름] | staging area에 올렸던 파일 다시 내리기 |
git status | Git이 현재 인식하고 있는 프로젝트 관련 내용들 출력 (문제 상황이 발생했을 때 현재 상태를 파악하기 위해 활용하면 좋음) |
git commit -m "커밋 메시지" | 현재 staging area에 있는 것들 커밋으로 남기기 |
git help [커맨드 이름] | 사용법이 궁금한 Git 커맨드의 공식 메뉴얼 내용 출력 |
git push -u(또는 --set-upstream) origin master | 로컬 레포지토리의 내용을 처음으로 리모트 레포지토리에 올릴 때 사용 |
git push | 로컬 레포지토리의 내용을 리모트 레포지토리에 보내기 |
git pull | 리모트 레포지토리의 내용을 로컬 레포지토리로 가져오기 |
git clone [프로젝트의 GitHub 상 주소] | GitHub에 있는 프로젝트를 내 컴퓨터로 가져오기 |
git log | 커밋 히스토리를 출력 |
git log --pretty=oneline | 커밋 하나당 히스토리 1개를 출력 |
git show [커밋 아이디] | 특정 커밋에서 어떤 변경사항이 있었는지 확인 |
git commit --amend | 최신 커밋을 다시 수정해서 새로운 커밋으로 만듦 |
git config alias.[별명] [커맨드] | 길이가 긴 커맨드에 별명을 붙여서 이후로 별명으로 해당 커맨드를 실행할 수 있도록 설정 |
git diff [커밋 A의 아이디][커밋 B의 아이디] | 두 커밋 간의 차이 비교 |
git reset [옵션][커밋 아이디] | (1) HEAD가 특정 커밋을 가리키도록 이동시킴(--soft는 여기까지 수행) (2) staging area도 특정 커밋처럼 리셋(--mixed는 여기까지 수행) (3) working directory도 특정 커밋처럼 리셋(--hard는 여기까지 수행) 그리고 이때 커밋 아이디 대신 HEAD의 위치를 기준으로 한 표기법(예 : HEAD^, HEAD~3)을 사용해도 됨 |
git tag [태그 이름][커밋 아이] | 특정 커밋에 태그를 붙임 |
git branch [새 브랜치 이름] | 새로운 브랜치를 생성 |
git checkout -b [새 브랜치 이름] | 새로운 브랜치를 생성하고 그 브랜치로 바로 이동 |
git branch -d [기존 브랜치 이름] | 브랜치 삭제 |
git checkout [기존 브랜치 이름] | 그 브랜치로 이동 |
git merge [기존 브랜치 이름] | 현재 브랜치에 다른 브랜치를 머지 |
git merge --abort | 머지를 하다가 conflict가 발생했을 때, 일단 머지 작업을 취소하고 이전 상태로 돌아감. |
git fetch | 로컬 레포지토리에서 현재 HEAD가 가리키는 브랜치의 업스트림(upstream) 브랜치로부터 최신 커밋들을 가져옴(가져오기만 한다는 점에서, 가져와서 머지까지 하는 git pull과는 차이가 있음) |
git blame | 특정 파일의 내용 한줄한줄이 어떤 커밋에 의해 생긴 것인지 출력 |
git revert | 특정 커밋에서 이루어진 작업을 되돌리는(취소하는) 커밋을 새로 생성 |
git reflog | HEAD가 그동안 가리켜왔던 커밋들의 기록을 출력 |
git log --all --graph | 모든 브랜치의 커밋 히스토리를, 커밋 간의 관계가 잘 드러나도록 그래프 형식으로 출력 |
git rebase [브랜치 이름] | A, B 브랜치가 있는 상태에서 지금 HEAD가 A 브랜치를 가리킬 때, git rebase B를 실행하면 A, B 브랜치가 분기하는 시작점이 된 공통 커밋 이후로부터 존재하는 A 브랜치 상의 커밋들이 그대로 B 브랜치의 최신 커밋 이후로 이어붙여짐(git merge와 같은 효과를 가지지만 커밋 히스토리가 한 줄로 깔끔하게 된다는 차이점이 있음) |
git stash | 현재 작업 내용을 스택 영역에 저장 |
git stash apply [커밋 아이디] | 스택 영역에 저장된 가장 최근의(혹은 특정) 작업 내용을 working directory에 적용 |
git stash drop [커밋 아이디] | 스택 영역에 저장된 가장 최근의(혹은 특정) 작업 내용을 스택에서 삭제 |
git stash pop [커밋 아이디] | 스택 영역에 저장된 가장 최근의(혹은 특정) 작업 내용을 working directory에 적용하면서 스택에서 삭제 |
git cherry-pick [커밋 아이디] | 특정 커밋의 내용을 현재 커밋에 반영 |
Git을 GUI 환경에서 사용할 수 있게 해주는 프로그램
→ GitKraken, Sourcetree
'코드잇 Codeit > CS / 기타' 카테고리의 다른 글
[코드잇] 웹 API 디자인 (0) | 2024.07.04 |
---|---|
[코드잇] 정규 표현식 (0) | 2024.01.30 |
[코드잇] 유닉스 커맨드 (0) | 2024.01.30 |
[코드잇] 챗GPT 활용하기 - 강의 내용 요약 및 후기 (8) | 2023.05.31 |
[코드잇] 프로그래밍 오버뷰 (프로그래밍 분야와 학습 가이드) (0) | 2023.04.08 |