본문 바로가기

[IT/Programming]

Git 을 배워보자. (Feat. GitHub)

728x90
반응형
# Git 을 배워보자. (Feat. GitHub) 버전 관리와 협업에 필수인 Git (and GitHub) 에 대해 배워봅시다. ## PH
  • 2024-07-30 : First posting.
## TOC ## Git 설치 및 간단한 명령어들 Git 은 (Global Information Tracker) 의 약자로 대충 보면 된다. (처음 이름 지은 사람은 이런 의도를 가진 약자가 아니었던 같긴 한데... 저 표현이 Git 을 잘 나타내준다고 본다.) 우선 설치: 에서 다운 받고 대충 설치. ```[.scrollable] SET BASEDIR=%CD% set GIT_EDITOR=vim set VISUAL=vim set EDITOR=%VISUAL% git config --global core.editor "vim" git config --global alias.history "log --pretty=oneline" git config --global user.name "kipid" git config --global user.email "kipacti@gmail.com" git config --global --replace-all init.defaultBranch main git config --global pull.rebase true git history git init // 버전 관리 시작하기 // git config 는 여러번 해서 덮어 씌울 수 있음. git add calculator.py git add License git commit -m "Create calculator.py and License" // commit message (-m) git status // 현재 상태 보기 git add . // 모든 파일 staging area 로 추가하기 git reset calculator.py // staging area 에서 제거하기 git reset . // 모든 파일 staging area 에서 제거 git help add // Manual 보기 ```/ Git은 내부적으로 크게 3가지 종류의 작업 영역을 두고 동작
  1. 첫 번째 작업 영역인 working directory 는 작업을 하는 프로젝트 디렉토리를 말합니다. 그러니까 지금 상황에서는 MathTool 디렉토리가 working directory 입니다.
  2. 두 번째 작업 영역인 staging area 는 git add 를 한 파일들이 존재하는 영역입니다. 커밋을 하게되면 staging area 에 있는 파일들만 커밋에 반영됩니다.
  3. 세 번째 작업 영역인 repository 는 working directory 의 변경 이력들이 저장되어 있는 영역입니다. 그러니까 커밋들이 저장되는 영역이라는 뜻입니다. (보통 .git 폴더를 나타내기도 하고, .git 폴더 포함 working directory 전체를 이야기하기도 하는듯.)
### Windows git config/settings (윈도우에서 깃 세팅) 다음과 같은 gitconfig.bat 파일을 만들어서 git_설치폴더\bin 폴더에 넣어놓자. 시스템 환경 변수는 적절히 PATH 값을 설정해줘야 하긴 한다. ```[.scrollable.lang-bat] // --global 태그를 추가로 달면 터미널 껐다켜도 유지가 되는건가? 잘 모르겠네 ㅡ,.ㅡ;;; SET BASEDIR=%CD% set GIT_EDITOR=vim set VISUAL=vim set EDITOR=%VISUAL% git config --global core.editor "vim" git config --global alias.history "log --pretty=oneline" git config --global user.name "kipid" git config --global user.email "kipacti@gmail.com" git config --global --replace-all init.defaultBranch main git config --global pull.rebase true cd [Repo-name directory] git config --global credential.helper path/to/the/password/github-pwd git remote set-url origin https://kipid:[password]@github.com/kipid/[Repo-name].git git pull ```/ Cmd 창이나 Shell 혹은 Cmder 에서 gitconfig 만 치면 설정 완료. 이렇게 해놓으면 다음부터 비번을 물어보지 않는다. ### GitHub Desktop (GUI: Graphical User Interface)
새로 생성되거나 편집된 파일을 체크해 줌으로서 git add 효과를 냄. Git -m (message) 도 "Create: Git 을 배워보자" 로 git commit. (Description 은 좀 더 구체적으로 설명을 붙이고 싶을때 쓰임.)
git push 할 준비가 됨. Push origin 으로 외부서버인 GitHub 에 해당 버전의 commit 을 push.
git pushed. GitHub 에 새로운 버전의 commit 이 있었다면 git fetch origin 으로 다운. 새 이미지를 저장해서 git-push.png 가 staging 된 것을 볼 수 있음.
Git history 탭에서 그동안 commit 한 git 들을 모아볼 수 있음. 이건 나 혼자써서 branch 가 main 으로 하나지만 협업을 할 때는 branch 가 여러개가 되고 git merge 가 되는 등의 작업이 일어날 수 있음.
이렇게 GUI (Graphical User Interface) 를 써서 git 을 다루는게 (GitHub 와 같이) 더 배우기도 쉽고 편하긴 한데... 굳이 git command 들을 외우고 Command Line Interface (CLI) 에서 작업해야 하는가가 의문이긴 함. 뭐 여러 복잡스런 작업들은 git command 로만 가능하거나 GUI 로는 더 복잡스러울수도 있을거 같긴 한데... 그럴일이 그렇게 많을거 같지도 않아서... 우선은 수업이 있으니 배워놓긴 할 예정. 안써서 금방 까먹을거 같긴 하지만...
p.s. 수업을 다 듣고 나니 배우는건 좀 많은듯. 이러한 기능들도 있었구나를 느꼈고, 더 잘 GitHub 를 활용할 수 있을거 같음.
## Git commands 정리
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 add . : working directory 내의 수정사항이 있는 모든 파일들을 staging area에 올리기 git reset [파일 이름] : staging area에 올렸던 파일 다시 내리기 git status : Git이 현재 인식하고 있는 프로젝트 관련 내용들 출력(문제 상황이 발생했을 때 현재 상태를 파악하기 위해 활용하면 좋음) git commit -m "커밋 메시지" : 현재 staging area에 있는 것들 커밋으로 남기기 git help [커맨드 이름] : 사용법이 궁금한 Git 커맨드의 공식 메뉴얼 내용 출력
## GitHub 와의 연계 ```[.scrollable] git remote add origin https://github.com/kipid/Example_Repository.git git branch -M main git branch -d master // or git branch -d --remote origin/master git push -u origin main // Id 비번으로 인증. => GitHub 패스워드가 아닌 토큰(token)을 입력. git commit -m "Message" git push git pull // remote repository 에 있는 commit 들 가져오기. ```/ ### 다른 사람도 내 repository 에 git push 할 수 있게 만들기 상단의 여러 탭 중에서 Settings 탭을 클릭하세요. 그 다음 화면 왼쪽의 Manage access 탭을 클릭. Invite a collaborator => Add ... to Example_Repository ## 다른 사람의 repository 내 컴퓨터로 가져오기 ```[.scrollable] git clone https://github.com/numpy/numpy.git git push -u origin main : 로컬 레포지토리의 내용을 처음으로 리모트 레포지토리에 올릴 때 사용합니다.(-u origin main 가 무슨 뜻인지는 'Git에서 브랜치 사용하기' 챕터에서 배울 거니까 걱정마세요!) git push : 로컬 레포지토리의 내용을 리모트 레포지토리에 보내기 git pull : 리모트 레포지토리의 내용을 로컬 레포지토리로 가져오기 git clone [프로젝트의 GitHub 상 주소] : GitHub에 있는 프로젝트를 내 컴퓨터로 가져오기 ```/ ## Git history ```[.scrollable] git log git log --pretty=oneline git show [commit-id/hash] git commit // 긴 commit message 를 남길 수 있음. git commit --amend // 이전 commit 수정하기. ```/ 변경 이력: 델타 (delta) \Delta difference
GitHub GUI (Graphical User Interface) 에서 git commit --amend 하기
## 커밋 메시지 작성 가이드라인 (1) 커밋 메시지의 제목과 상세 설명 사이에는 한 줄을 비워두세요. (2) 커밋 메시지의 제목 뒤에 온점(.)을 붙이지 마세요. (3) 커밋 메시지의 제목의 첫 번째 알파벳은 대문자로 작성하세요. (4) 커밋 메시지의 제목은 명령조로 작성하세요.(Fix it / Fixed it / Fixes it) (5) 커밋의 상세 내용에는 이런 걸 적으면 좋습니다.
  • 왜 커밋을 했는지
  • 어떤 문제가 있었고
  • 적용한 해결책이 어떤 효과를 가지는지
(6) 다른 사람들이 자신의 코드를 바로 이해할 수 있다고 가정하지 말고 최대한 친절하게 작성하세요. ## 커밋할 때 알아야할 가이드라인 (1) 하나의 커밋에는 하나의 수정사항, 하나의 이슈(issue)를 해결한 내용만 남기도록 하세요. 다양하게 수정을 하고나서 하나의 커밋으로 남기는 것은 좋지 않습니다. 하나의 커밋이 하나의 사실만을 갖고 있어야 나중에 이해하기 쉽습니다. (2) 현재 프로젝트 디렉토리의 상태가 그 내부의 전체 코드를 실행했을 때 에러가 발생하지 않는 상태인 경우에만 커밋을 하도록 하세요. 나중에 동료 개발자가 특정 커밋의 코드로 실행했을 때 에러가 발생한다면 혼란을 줄 수 있습니다.
  • 나중에 다시 봤을 때 이해하는데 어려움이 없도록
  • 다른 동료 개발자와 협업하는 데 방해가 되지 않도록
## 긴 커맨드에 alias 설정하기 ```[.scrollable] git config alias.history "log --pretty=oneline" --global // git histroy 라고만 써도 자동으로 git log --pretty=oneline 을 실행하게 됨. git history ```/ ## 두 commit 간의 차이 보기 ```[.scrollable] git diff [커밋 A의 아이디] [커밋 B의 아이디] ```/ ## HEAD (이전 commit 으로 git reset 하기) HEAD: 어떤 commit 하나를 가리킴. ```[.scrollable] git reset --hard [커밋 아이디] // 과거 commit 으로 아예 돌아가고 싶을 때 (꽤나 위험한 명령어. 뒷쪽 commit 들이 모두 날라감. 완전히 날라가는건 아니고 git reflog 로만 볼 수 있음.) git reset [option] HEAD^ // 이전 commit git reset [option] HEAD~n // n번째 전 commit ```/
GitHub 에서 git reset 하기. Revert changes in commit. GitHub 에선 reset 이후의 commit 들도 history 로 그대로 남아있긴 함. 덮어 씌우는게 아니라. 그래서 다시 돌아갈수도 있음.
### git reset을 쓸 때 --hard는 뭐였을까? ```[.scrollable] git reset --hard [커밋 아이디] git reset --soft [커밋 아이디] git reset --mixed [커밋 아이디] ```/
git reset [옵션] [Commit ID]
### staging area 에 있던 것들은 커밋하고 나면 어떻게 될까? 커밋을 했다고 staging area 가 초기화되거나 하지는 않는 겁니다. 계속 git add 를 할 때마다 staging area 에서는 새로운 파일이 추가되거나 원래 있던 파일이 더 새로운 버전의 것으로 교체되거나 할 뿐입니다. staging area 에 있던 것들은 커밋을 하더라도 그것과 상관없이 계속 남아있다는 점. ## Commit 에 tag 달기 ```[.scrollable] git tag [태그 이름] [커밋 아이디] git tag // 프로젝트 디렉토리에 있는 모든 태그를 조회 git show [태그 이름] // 태그와 연결된 커밋이 보고 싶으면 ```/
GitHub GUI (Graphical User Interface) 에서 git tag 달기.
## Git commands 정리
git log : 커밋 히스토리를 출력 git log --pretty=oneline : --pretty 옵션을 사용하면 커밋 히스토리를 다양한 방식으로 출력할 수 있습니다. --pretty 옵션에 oneline이라는 값을 주면 커밋 하나당 한 줄씩 출력해줍니다. --pretty 옵션에 대해 더 자세히 알고싶으면 이 링크를 참고하세요. git show [커밋 아이디] : 특정 커밋에서 어떤 변경사항이 있었는지 확인 git commit --amend : 최신 커밋을 다시 수정해서 새로운 커밋으로 만듦 git config alias.[별명] [커맨드] : 길이가 긴 커맨드에 별명을 붙여서 이후로 별명으로 해당 커맨드를 실행할 수 있도록 설정 git diff [커밋 A의 아이디] [커밋 B의 아이디] : 두 커밋 간의 차이 비교 git reset [옵션] [커밋 아이디] : 옵션에 따라 하는 작업이 달라짐(옵션을 생략하면 --mixed 옵션이 적용됨)
(1) HEAD가 특정 커밋을 가리키도록 이동시킴(--soft는 여기까지 수행) (2) staging area도 특정 커밋처럼 리셋(--mixed는 여기까지 수행) (3) working directory도 특정 커밋처럼 리셋(--hard는 여기까지 수행)
그리고 이때 커밋 아이디 대신 HEAD의 위치를 기준으로 한 표기법(예 : HEAD^, HEAD~3)을 사용해도 됨 git tag [태그 이름] [커밋 아이디] : 특정 커밋에 태그를 붙임
## Branch Branch: 나뭇가지. 하나의 코드 관리 흐름. master branch or main branch (요새는 main 으로 주로 이름 붙임.) ```[.scrollable] git branch premium // premium branch 만들기 git checkout premium // premium branch 로 이동 git branch // branch 조회 git branch -d test // delete branch git checkout -b test // branch 생성 및 이동 git checkout main // main branch 로 이동 ```/ ### Branch merge 하기 ```[.scrollable] git checkout premium git merge main // 현재 premium branch 에 main branch merge 하기 ```/ #### Merge conflict 1. Conflict 가 발생한 파일을 연다. 2. Merge 의 결과가 되었으면 하는 모습대로 코드를 수정. 3. Commit. or ```[.scrollable] git merge --abort // Merge 취소 ```/ #### 여러 파일에서 conflict 가 났을 때 파일 하나씩 conflict 를 해결하고 git add [파일 이름] 커맨드로 하나씩 staging area 에 올리거나(중간중간에 git status 커맨드로 현재 상태 확인하면서) 모든 파일들의 conflict 를 다 해결하고, git add . 커맨드로 한번에 staging area 에 올리고 커밋을 하면 됩니다. ### Remote Repository 의 브랜치는 이렇게 보입니다! #### origin 이란? ```[.scrollable] git remote add origin https://github.com/kyuri-dev/Math_Box.git git push -u origin main // -u 는 --set-upstream 이라는 옵션의 약자 ```/ Git 에서는 리모트 레포지토리를 최초로 추가할 때 origin 이라는 이름으로 가리키는 것이 관례화되어 있습니다. origin 은 '근원', '기원' 이라는 뜻을 가집니다. 아마도 다른 사람의 리모트 레포지토리를 자신의 컴퓨터로 가져와서 작업을 하는 사람의 입장에서는 리모트 레포지토리가 프로젝트의 근원이 되는 존재이기 때문에 그런 관습이 생긴 것으로 추측됩니다. #### Remote Repositoy 에 있는 브랜치 ```[.scrollable] git push origin main:main // origin 은 리모트 레포지토리를 나타내고, main:main 에서 더 먼저 나오는 main 는 로컬 레포지토리의 main 브랜치(~에서)/더 뒤에 나오는 main 는 리모트 레포지토리의 main 브랜치(~으로)를 나타냅니다. ```/ 그냥 처음부터 tracking connection 을 설정하고 그 이후부터는 git push, git pull 이라고만 써서 편하게 푸시와 풀을 하는 게 좋겠죠? 이게 바로 제가 맨 처음에 로컬 레포지토리의 내용을 리모트 레포지토리로 보낼 때 -u 라는 옵션을 썼던 이유입니다. ```[.scrollable] git push -u origin main // tracking connection 설정 ```/ #### origin/main 의 의미 git push 를 해준 적이 없다면, Local repository 의 main branch 가 나타내는 commit 들과 origin/main 인 remote repository 의 main branch 를 나타내는 commit 이 다를 수 있음. git push 로 통합시킬 수 있음. #### Remote repository 에 새로운 branch 추가하기 ```[.scrollable] git checkout premium git push --set-upstream origin premium // premium branch 를 remote 로 처음 push 할 때 ```/ ## HEAD 와 Branch 의 관계 Branch 는 코드를 관리하는 하나의 흐름. Branch 는 Commit 을 가리키는 포인터. HEAD 는 branch 를 가리킴. Merge commit: 두 branch 가 하나로 합쳐짐. 합쳐진 branch 를 HEAD 가 가리킴. git reset 커맨드를 사용하면
  1. HEAD는 여전히 같은 브랜치를 가리키고,
  2. HEAD가 가리키는 브랜치가 다른 특정 커밋을 가리키게 됩니다.
  3. 이 때문에 결국 HEAD가 간접적으로 가리키던 커밋도 바뀌게 되는 겁니다.
git reset에 관해서 분명하게 아셔야할 게
  1. 과거의 커밋으로 git reset을 한다고 그 이후의 커밋들이 삭제되는 게 절대 아닙니다. 계속 남아있습니다.
  2. git reset은 과거의 커밋뿐만 아니라 현재 HEAD가 가리키는 커밋 이후의 커밋으로도 할 수 있습니다.
### Detached HEAD 브랜치를 통해서 커밋을 가리키는 게 아니라 본인이 직접 커밋을 가리키고 있는 상태의 HEAD를 특별히 가리키는 말. ```[.scrollable] git checkout [Commit ID] ```/ Detached 는 우리말로 ‘~로부터 떨어진, 분리된’이라는 뜻을 갖는데요. 브랜치로부터 떨어진 상태이기 때문에 이렇게 부르는 겁니다.
git checkout 커맨드로는 HEAD 가 직접적으로 가리키는 것을 바꿀 수 있고 git checkout 뒤에는 커밋 아이디 또는 브랜치의 이름을 줘서 HEAD 가 직접 커밋을 가리키거나, 브랜치를 가리키도록 할 수 있다는 뜻입니다.
git reset: HEAD 가 가리키던 브랜치가 다른 커밋을 가리키도록 한다. HEAD 도 결국 간접적으로 다른 커밋을 가리키게되는 효과가 생긴다 git checkout: HEAD 자체가 다른 커밋이나 브랜치를 가리키도록 한다. 브랜치를 통하지 않고, 커밋을 직접적으로 가리키는 HEAD 를 Detached HEAD 라고 한다
## Merge commit ### 3-way merge Merge 를 하면 새로운 commit 이 생긴다. 이를 Merge commit 이라고 부른다.
3-way merge
case1
지금 base 가 A이고, main 는 A, premium 은 B죠? 그럼 base 를 기준으로 볼 때, main 에서는 변화가 없었지만, premium 에서는 A 가 B 로 변경된 상태입니다. 3-way merge 는 base 에서 변화가 발생한 것을 우선 채택합니다. 그래서 머지 결과는 'B' 가 됩니다.
case2
지금 base 가 1이고, main 는 2, premium 은 1이죠? 이 경우에도 base 에서 변화가 발생한 2가 머지 결과가 됩니다.
case3
지금 base 가 "hello" 이고, main 는 "hello" 를 삭제한 공백 상태, premium 은 "hello" 입니다. "hello" 를 삭제해서 공백 상태가 된 것이 변화가 더 발생한 것이기 때문에 머지 결과는 공백이 됩니다.
case4
지금 base 가 "bye", main 가 "fighting", premium 이 "please" 인데요. 지금은 이전 경우들과 좀 다르네요. 둘 다 base 때와는 다른 변화가 일어났는데요. 이렇게 두 브랜치에서 다 변화가 있을 때 Git 은 어떤 변화를 선택해야할까요? 정답은 바로 'Git도 모른다!' 입니다. 사실, 바로 이런 경우에 여러분이 배운 Conflict 가 발생합니다. 이전에 Conflict 가 발생했을 때 그것을 해결하고 머지를 마무리했던 거 기억나시죠? 바로 이런 경우였던 겁니다.
종합 정리
base때의 내용과 비교했을 때 달라진 부분이 있는 것이 우선시되고, 두 브랜치에서 둘다 변화가 일어났을 때는 Conflict를 발생시켜서 사용자가 스스로 선택하게끔 한다는 걸 기억하시면 됩니다.
### Merge commit 이 안생기는 경우: Fast-forward merge 커밋 히스토리에서 같은 선 (line) 상에 있는 브랜치를 머지할 때 Fast-forward 머지가 이루어집니다. ## Git commands 정리
git branch [새 브랜치 이름]: 새로운 브랜치를 생성 git checkout -b [새 브랜치 이름]: 새로운 브랜치를 생성하고 그 브랜치로 바로 이동 git branch -d [기존 브랜치 이름]: 브랜치 삭제 git checkout [기존 브랜치 이름]: 그 브랜치로 이동 git merge [기존 브랜치 이름]: 현재 브랜치에 다른 브랜치를 머지 git merge --abort: 머지를 하다가 conflict가 발생했을 때, 일단은 머지 작업을 취소하고 이전 상태로 돌아감
## git pull (or fetch) git push 를 하기 전에 보통 git pull (or fetch) 을 먼저 해야한다. 이 경우 conflict 가 나는 경우가 많을텐데, 이런 conflict 를 잘 해결한 뒤 git commit 을 해야한다.
git pull = git fetch + git merge
### git fetch 우선 commit 들을 merge 없이 가져오는 명령어. Remote repository 에서 가져온 branch 의 내용을 merge 하기 전에 점검해야할 필요가 있을 때 사용. Remote repository 에 있는 branch 의 내용과 내가 작성한 코드를 비교해서 잘못된 부분이 없는지 검토해야 할 때. ```[.scrollable] git fetch git diff premium origin/premium // 두 local branch 와 remote branch 를 비교 ```/ ## git blame [filename] file 의 각 부분이 어떤 commit 으로 수정되었는지 보여주는 명령어. (이건 GitHub GUI (Graphical User Interface) 에서 잘 못봤던거 같은데, 찾아봐야겠음.) :: GitHub.com file page 에서 blame 이란 옵션이 왼쪽 위에 있는듯. 그걸 클릭하면 file 의 각 부분이 어떤 commit 으로 수정되었는지 보여줌. ### git show [commit id] commit 의 내용 (file 의 변화된 부분, commit message 등) 보여주기. ## git revert [commit id] Commit 을 되돌리는 명령어. Commit 이 하나 더 만들어짐 (Revert commit). 이후 commit 들을 아예 지워버리는 git reset 보다 더 많이 활용될듯. ### git revert [복귀 될 commit id]..[초기화 할 commit 들 중 가장 나중 commit id] // (여러개 commit 들을 한꺼번에 revert 하기) ```[.scrollable] git revert [복귀 될 commit id]..[초기화 할 commit 들 중 가장 나중 commit id] // 여러개의 revert commit 들이 생김 ```/ ## Git commands 정리
git fetch: 로컬 레포지토리에서 현재 HEAD 가 가리키는 브랜치의 업스트림 (upstream) 브랜치로부터 최신 커밋들을 가져옴 (가져오기만 한다는 점에서, 가져와서 머지까지 하는 git pull 과는 차이가 있음) git blame: 특정 파일의 내용 한줄한줄이 어떤 커밋에 의해 생긴 것인지 출력 git revert: 특정 커밋에서 이루어진 작업을 되돌리는 (취소하는) 커밋을 새로 생성
## git reflog: git reset 후의 commit 들 (git reset 을 하고 나서 돌아오려면?) ```[.scrollable] git reflog // reference log, reset 이전/이후의 commit 들도 보기 ```/ ## git log --pretty=oneline --all --graph branch 도 같이 표현해주면서 예쁘게 git history 를 보여주는 명령어. ## Git GUI (Graphical User Interface): SourceTree SourceTree https://www.sourcetreeapp.com/ 란 Git GUI 가 있다는거 같음. GitHub Desktop 도 좋긴 하던데, 두 프로그램의 장단점이 있긴 할 듯. 둘 다 깔아서 사용해 볼 예정. ## 깔끔한 커밋 히스토리를 원할 땐 git merge 대신 git rebase [branch name] ```[.scrollable] git rebase [branch name] git rebase --continue // Conflict 가 발생해서 제대로 진행되지 못한 rebase 를 계속 진행하라 ```/ merge 보다 commit history 가 더 깔끔하단 장점이 있음. 상황에 따라 git rebase, git merge 를 잘 활용합시다. ## git stash: 작업 내용 임시 저장하기 ```[.scrollable] git stash // 작업했던/수정했던 파일들을 stack 에 잠기 옮겨둠 git stash list git stash apply // 작업했던/수정했던 파일들을 복구 ```/ ### 잘못된 브랜치에서 작업하고 있었다면? ```[.scrollable] git checkout main git stash git checkout premium git stash apply // 다른 branch 에서도 stash apply 를 쓸 수 있음. 작업 내용의 아이디를 생략하면 가장 최근의 작업 내용이 적용됨. git stash list // stash@{0}: WIP on master: 75282b7 Add free License duration info // stash@{1}: WIP on premium: 84e67c3 Add get_Remainder function git stash apply stash@{0} // 특정 stash 를 적용하고 싶을 때. git stash drop stash@{0} // 이미 stash apply 를 하고 commit 을 했다면 stash stack 에서 지워줍시다. git stash pop [작업 내용의 아이디] // git stash apply 를 해주고 바로 git stash drop 을 해줌. [작업 내용의 아이디] 가 없다면 제일 최근의 stash 에 적용. ```/ 일반적으로 git stash pop 이 주로 더 많이 사용됨. ## 필요한 커밋만 가져오는 git cherry-pick 다른 branch 의 더 오래된 commit 을 가져다 오고 싶을때 주로 쓰임. ```[.scrollable] git cherry-pick [commit id] ```/ ## 여러 커밋을 하나의 커밋으로 만들기 (심화) ```[.scrollable] git reset --soft [commit id] // 없애고 싶은 자잘한 commit 들이 있을때 reset to last commit with --soft option. git add . git commit -m "Message" ```/ ## .gitignore: git 이 무시하는 파일들 굳이 Git 에 의해 버전 관리될 필요가 없는, 불필요한 파일들의 이름을 정리하여 .gitignore 파일을 생성.
버전 관리를 할 정도의 가치가 없고, 오히려 버전 관리를 하면 용량만 더 차지하고, 나중에 각 버전을 살펴볼 때 가독성을 떨어뜨리기만 하기 때문에
그런데 먼저 commit 을 한 후에 .gitignore 에 추가를 하면, file 들이 계속 추적되는 경우가 있다. 이 경우 아래와 같은 명령어를 치면 되는듯 하다. .gitignore 설정하기 ```[.scrollable] git rm -r --cached . git add . git commit -m "Apply .gitignore" ```/ 예: ```[.scrollable] # .gitignore ### Vert.x ### .vertx/ ### Eclipse ### .metadata bin/ tmp/ *.tmp *.bak *.swp *~.nib local.properties .settings/ .loadpath .recommenders # External tool builders .externalToolBuilders/ # Locally stored "Eclipse launch configurations" *.launch # PyDev specific (Python IDE for Eclipse) *.pydevproject # CDT-specific (C/C++ Development Tooling) .cproject # Java annotation processor (APT) .factorypath # PDT-specific (PHP Development Tools) .buildpath # sbteclipse plugin .target # Tern plugin .tern-project # TeXlipse plugin .texlipse # STS (Spring Tool Suite) .springBeans # Code Recommenders .recommenders/ # Scala IDE specific (Scala & Java development for Eclipse) .cache-main .scala_dependencies .worksheet ### Intellij+iml ### # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and Webstorm # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 # User-specific stuff: .idea/**/workspace.xml .idea/**/tasks.xml .idea/dictionaries # Sensitive or high-churn files: .idea/**/dataSources/ .idea/**/dataSources.ids .idea/**/dataSources.xml .idea/**/dataSources.local.xml .idea/**/sqlDataSources.xml .idea/**/dynamic.xml .idea/**/uiDesigner.xml # Gradle: .idea/**/gradle.xml .idea/**/libraries # CMake cmake-buildTool-debug/ # Mongo Explorer plugin: .idea/**/mongoSettings.xml ## File-based project format: *.iws ## Plugin-specific files: # IntelliJ /out/ # mpeltonen/sbt-idea plugin .idea_modules/ # JIRA plugin atlassian-ide-plugin.xml # Cursive Clojure plugin .idea/replstate.xml # Crashlytics plugin (for Android Studio and IntelliJ) com_crashlytics_export_strings.xml crashlytics.properties crashlytics-buildTool.properties fabric.properties ### Intellij+iml Patch ### # Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-249601023 *.iml modules.xml .idea/misc.xml *.ipr ### macOS ### *.DS_Store .AppleDouble .LSOverride # Icon must end with two \r Icon # Thumbnails ._* # Files that might appear in the root of a volume .DocumentRevisions-V100 .fseventsd .Spotlight-V100 .TemporaryItems .Trashes .VolumeIcon.icns .com.apple.timemachine.donotpresent # Directories potentially created on remote AFP share .AppleDB .AppleDesktop Network Trash Folder Temporary Items .apdisk ### Maven ### target/ pom.xml.tag pom.xml.releaseBackup pom.xml.versionsBackup pom.xml.next release.properties dependency-reduced-pom.xml buildNumber.properties .mvn/timing.properties # Avoid ignoring Maven wrapper jar file (.jar files are usually ignored) !/.mvn/wrapper/maven-wrapper.jar ### Gradle ### .gradle /buildTool/ # Ignore Gradle GUI config gradle-app.setting # Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored) !gradle-wrapper.jar # Cache of project .gradletasknamecache # # Work around https://youtrack.jetbrains.com/issue/IDEA-116898 # gradle/wrapper/gradle-wrapper.properties ### NetBeans ### nbproject/private/ buildTool/ nbbuild/ dist/ nbdist/ .nb-gradle/ ### VisualStudioCode ### .vscode/* !.vscode/settings.json !.vscode/tasks.json !.vscode/launch.json !.vscode/extensions.json # Sublime text *.sublime-workspace *.sublime-project *.log *.mdmp build/distributions/http-1.0.0-SNAPSHOT.tar build/distributions/http-1.0.0-SNAPSHOT.zip build/libs/http-1.0.0-SNAPSHOT-fat.jar build/libs/http-1.0.0-SNAPSHOT.jar build/distributions/http-shadow-1.0.0-SNAPSHOT.tar build/distributions/http-shadow-1.0.0-SNAPSHOT.zip cmder/config/* cmder/vendor/conemu-maximus5/ConEmu.xml ```/ ## Git 토픽 내용 총정리 자, 이제 마지막 챕터까지 모든 내용을 마쳤습니다. 이때까지 배운 Git 커맨드를 챕터별로 한눈에 살펴볼까요? 코드잇 :: Git - 14. Git 토픽 내용 총정리 ### Git 써보기
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 add . : working directory 내의 수정사항이 있는 모든 파일들을 staging area에 올리기 git reset [파일 이름] : staging area에 올렸던 파일 다시 내리기 git status : Git이 현재 인식하고 있는 프로젝트 관련 내용들 출력(문제 상황이 발생했을 때 현재 상태를 파악하기 위해 활용하면 좋음) git commit -m "커밋 메시지" : 현재 staging area에 있는 것들 커밋으로 남기기 git help [커맨드 이름] : 사용법이 궁금한 Git 커맨드의 공식 메뉴얼 내용 출력
### GitHub 시작하기
git push -u(또는 --set-upstream) origin master : 로컬 레포지토리의 내용을 처음으로 리모트 레포지토리에 올릴 때 사용합니다. git push : 위의 커맨드를 한번 실행하고 난 후에는 git push라고만 쳐도 로컬 레포지토리의 내용을 리모트 레포지토리에 올릴 수 있습니다. git pull : 바로 위의 위에 있는 커맨드를 한번 실행하고 난 후에는 git pull이라고만 쳐도 리모트 레포지토리의 내용을 로컬 레포지토리로 가져옵니다. git clone [프로젝트의 GitHub 상 주소] : GitHub에 있는 프로젝트를 내 컴퓨터로 가져오기
### Git에서 커밋 다루기
git log : 커밋 히스토리를 출력 git log --pretty=oneline : --pretty 옵션을 사용하면 커밋 히스토리를 다양한 방식으로 출력할 수 있습니다. --pretty 옵션에 oneline이라는 값을 주면 커밋 하나당 한 줄씩 출력해줍니다. --pretty 옵션에 대해 더 자세히 알고싶으면 이 링크를 참고하세요. git show [커밋 아이디] : 특정 커밋에서 어떤 변경사항이 있었는지 확인 git commit --amend : 최신 커밋을 다시 수정해서 새로운 커밋으로 만듦 git config alias.[별명] [커맨드] : 길이가 긴 커맨드에 별명을 붙여서 이후로는 별명으로도 해당 커맨드를 실행할 수 있게 설정 git diff [커밋 A의 아이디] [커밋 B의 아이디] : 두 커밋 간의 차이 비교 git reset [옵션] [커밋 아이디] : 옵션에 따라 하는 작업이 달라짐(옵션을 생략하면 --mixed 옵션이 적용됨)
(1) HEAD가 특정 커밋을 가리키도록 이동시킴(--soft는 여기까지 수행) (2) staging area도 특정 커밋처럼 리셋(--mixed는 여기까지 수행) (3) working directory도 특정 커밋처럼 리셋(--hard는 여기까지 수행) 그리고 이때 커밋 아이디 대신 HEAD의 위치를 기준으로 한 표기법(예 : HEAD^, HEAD~3)을 사용해도 됨
git tag [태그 이름] [커밋 아이디] : 특정 커밋에 태그를 붙임
### Git에서 브랜치 사용하기
git branch [새 브랜치 이름] : 새로운 브랜치를 생성 git checkout -b [새 브랜치 이름] : 새로운 브랜치를 생성하고 그 브랜치로 바로 이동 git branch -d [기존 브랜치 이름] : 브랜치 삭제 git checkout [기존 브랜치 이름] : 그 브랜치로 이동 git merge [기존 브랜치 이름] : 현재 브랜치에 다른 브랜치를 머지 git merge --abort : 머지를 하다가 conflict가 발생했을 때, 일단은 머지 작업을 취소하고 이전 상태로 돌아감
### Git 실전
git fetch : 로컬 레포지토리에서 현재 HEAD가 가리키는 브랜치의 업스트림(upstream) 브랜치로부터 최신 커밋들을 가져옴(가져오기만 한다는 점에서, 가져와서 머지까지 하는 git pull과는 차이가 있음) git blame : 특정 파일의 내용 한줄한줄이 어떤 커밋에 의해 생긴 것인지 출력 git revert : 특정 커밋에서 이루어진 작업을 되돌리는(취소하는) 커밋을 새로 생성
### Git 실전 Ⅱ
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 [커밋 아이디] : 특정 커밋의 내용을 현재 커밋에 반영
! 그 밖에 알아야할 사실 (1) git commit이라고만 쓰고 실행하면 커밋 메시지를 입력할 수 있는 텍스트 에디터 창이 뜹니다. 거기서 커밋 메시지를 입력하고 저장하고 나면 커밋이 이루어집니다. (2) git push와 git pull은 그 작업 단위가 브랜치입니다. 예를 들어, master 브랜치에서 git push를 하면 master 브랜치의 내용만 리모트 레포지토리의 master 브랜치로 전송되지, premium 브랜치의 내용이 전송되는 것은 아닙니다.(git push에 --all이라는 옵션을 주면 모든 브랜치의 내용을 전송할 수 있기는 합니다.)
### 마무리 자, Git 토픽에서 배운 커맨드들을 쭉 정리해봤는데요. 기억이 다 잘 나시나요? 이 커맨드들만 제대로 이해하고 사용해도 여러분이 어디에서 어떤 일을 하든 Git을 사용할 때 불편함이 없을 겁니다. 혹시라도 Git으로 아주 세밀한 작업 또는 여기서 배우지 않은 새로운 커맨드를 써야한다고 할지라도 겁낼 필요가 없습니다. 이 토픽에서는 커맨드 뿐만 아니라 Git의 내부 동작 원리도 제대로 배웠기 때문에 여러분이 조금만 노력하면 그런 것들도 금방 쉽게 할 수 있을 겁니다. 이제 어디를 가도 '나 Git 쓸 줄 알아!' 라고 자신있게 말할 수 있게 되신 여러분, 축하합니다! ## 추신 (코드 리뷰 시스템: Gerrit) 코드 리뷰 시스템인 Gerrit 도 설치하고 공부해 볼만함. (구글에서 만든 code review framework 인거 같음.) https://gerrit-review.googlesource.com/Documentation/ 3개월간 Intern 을 했던 Skelter Labs 란 회사에서 쓰던 시스템인데, git commit 한걸 가지고 변경된 사항마다 이러이러한 부분이 수정이 필요한거 같단 리뷰/코멘트를 Graphical 하게 써서 리뷰를 보내줄 수 있고. 그 수정부분을 반영해서 다시 리뷰를 요청하고, 다시 리뷰 받고를 반복. 리뷰를 통과해야만 main branch 에 리뷰가 다 된 commit 들이 하나로 통합된 commit 하나가 merge 되는 시스템이었던 걸로 기억함. 리눅스 서버에 깔아야 하는거 같긴한데... 큰 회사나 스타트업들이 구축해놓으면 꽤 좋은거 같음. ## 여러 원격 저장소들
GitHub: 서비스가 죽는다. 대란 (업무 마비). 대중적. 관대하다. (많은 서비스들이 무료. 비공개 Repository 등.) GitLab: 설치형 BigBuckit: Figma: 서버가 죽으면 대란. AWS: 서비스 중단이면 대란.
## 협업시 Git/GitHub Tips 참조: ### Windows (윈도우) 에선 .bat, Mac 에선 .sh 만들어서 활용하면 좋음. kipid 는 자기 계정 이름으로 바꾸시고 아래와 같은 .bat 파일을 C:/PortableGit/bin 디렉토리에 복붙하면 됨. 환경변수 편집에서 PATH 에 C:/PortableGit/bin 도 추가해 주셔야 하고. ```[.linenums] @rem copy to C:/PortableGit/bin :: Current directory SET BASEDIR=%CD% set GIT_EDITOR=vim set VISUAL=vim set EDITOR=%VISUAL% git config --global core.editor "vim" git config --global alias.history "log --pretty=oneline" git config --global user.name "kipid" git config --global user.email "kipacti@gmail.com" git config --global --replace-all init.defaultBranch main git config --global pull.rebase true rem 자신의 이름과 이메일을 입력할 것. rem ssh 인증이 필요하다면 아래와 같은 명령어를 치면, 매번 git push/pull 마다 인증할 필요가 없어짐. rem call ssh-agent rem ssh-add C:/path/to/.ssh/github-recoeve-rsa rem git config --global credential.helper cache rem cd [Git-repo-name-1] rem git remote set-url origin git@github.com:kipid/[Git-repo-name-1].git rem git pull rem cd [Git-repo-name-1] rem git remote set-url origin git@github.com:kipid/[Git-repo-name-2].git rem git pull git config --global credential.helper C:/[Git-repo-name-2]/.ssh/github-pwd git remote set-url origin https://kipid:[temporal-password]@github.com/kipid/[Git-repo-name-1].git git pull cd C:/[Git-repo-name-2]/ git remote set-url origin https://kipid:[temporal-password]@github.com/kipid/[Git-repo-name-2].git git pull :: Back to current directory cd %BASEDIR% ```/ ### 다른 팀원에 의해 dev가 merge 된 경우 우선 dev branch 로 가서 dev 를 최신으로 동기화 한 뒤 내 작업 branch 로 가서 dev 로 merge 후 작업 이어서 진행. Merge 한다고 dev branch 가 바뀌는건 아님. ```[.linenums] (feature/my-job 브랜치에서 작업 도중 다른 팀원에 의해 dev가 merge 된 경우) git checkout dev git pull upstream dev git checkout feature/my-job git merge dev # 커밋메시지 변경 후 저장 # 작업이어서 진행 ```/ ### Project PR 머지 후 작업 ```[.linenums] git checkout dev git pull upstream dev git push origin dev ## 중요 git switch -c feature/next-job ```/ ### 빠르게 전체 팀원이 적용해야 할 변경사항을 dev 브랜치로 반영하면서, 동시에 아직 완료되지 않은 feature/my-job 브랜치 작업을 유지하려면 ```[.linenums] git stash ```/ 로 현재 feature/my-job branch 에서 작업하고 있는 내용을 임시로 저장. dev branch 로 가서 최신으로 동기화 시킨 뒤 새로운 branch 를 생성. (dev 기반으로 branch 가 생성됨.) ```[.linenums] git checkout dev git pull git checkout -b feature/hot-fix ```/ 필요한 변경 사항만 적용: 데이터베이스 테이블 수정과 같이 빠르게 반영해야 하는 사항만 이 브랜치에 커밋합니다. ```[.linenums] git add . git commit -m "fix: apply urgent DB table changes" git push ```/ To dev from feature/hot-fix 로 PR merge 요청. 바로 self merge 할 수 있음 하고, 1인이상 approve 해야 merge 되는 상황이라면 동료에게 알려서 빠르게 merge. Merge 된 dev branch 를 다시 최신 동기화. 그리고 원래 작업으로 복귀. ```[.linenums] git checkout dev git pull git checkout feature/my-job git stash pop git merge dev ```/ ### 충돌이 발생한 경우 충돌이 발생한 파일에서 충돌한 부분을 수정해야 합니다. Git은 충돌 부분을 다음과 같이 표시합니다. ``` <<<<<<< HEAD 이 부분은 feature/my-job 브랜치의 변경 내용입니다. ======= 이 부분은 dev 브랜치의 변경 내용입니다. >>>>>>> dev ```/ 두 내용을 비교하여 충돌을 해결한 후, 필요 없는 표시(<<<<<<<, =======, >>>>>>>)를 삭제합니다. 충돌을 해결한 후, 수정한 파일을 스테이징하고 커밋.
이 과정은 VS code 에서 잘 해결해 줌. (Extension 을 깔아서 그런건가? =ㅇ=) Accept current, Accept the following, Accept both 등이 충돌난 부분에 떴었던거 같음. 적절히 선택하면 빠르게 충돌을 해결할 수 있음.
### 모든 충돌을 dev 브랜치의 내용으로 해결 ``` git checkout --theirs . ```/ 라고 치면 충돌 부분에서 상대 브랜치 (dev branch) 의 내용을 선택한다는데... 이건 좀 조심해서 써야할듯. ## RRA
  1. Git - GIT 강의 | 코드잇
    Git 협업하기 - 강의 | 코드잇
  2. https://git-scm.com/
  3. shard-driver-9f8.notion.site :: 깃허브 tips
728x90
반응형