유저가 커널을 직접 다루기는 너무 어려워서 응용 소프트웨어로 간편한 제어 및 사용을 제공
#!/bin/sh
= 상단에 셔뱅(shebang)을 추가한 뒤 스크립트를 작성(Batch File)source ~/.bashrc
통해 설정 재로딩 가능~/**.bashrc**
(rc : run commands)~/**.bash_profile**
(혹은 ~/.bash_login
, ~/.profile
순서)~/**.bash_logout**
#!/bin/bash
source ~/.bashrc
통해 설정 재로딩이 가능~/**.zshrc**
(rc : run commands)~/**.zprofile**
또는 ~/**.zshenv**
~/.zsh_history
~/.zsh_sessions
#!/bin/zsh
pwd
: 현재 디렉토리의 절대경로ls
: 디렉토리 내 어떤 파일들이 있는지 조회 | ls **-la**
혹은 ll
사용 (a
모든걸, l
상세하게)cd
: 디렉토리 이동 (들어가거나, 나올때) | 이전 디렉토리 cd **..**
상대경로 cd **./x**
절대경로 cd **/x**
mkdir
: 새 디렉토리 생성rm
: 디렉토리 혹은 파일 삭제 | rm **-rf**
(r
리컬시브, 내부에 있는 디렉토리들 모두, f
강제로 삭제)cp
: 디렉토리 혹은 파일 복사 | cp
혹은 cp -r
(r
리컬시브, 내부에 있는 디렉토리들 모두)mv
: 디렉토리 혹은 파일 이동 혹은 명칭 변경touch
: 아무것도 없는 빈 파일 생성cat
: 파일 출력echo
: 문자열 출력, 일반적으로 환경변수 값을 확인하는데에 사용 | echo $ZSH_CUSTOM
export ZSH_CUSTOM="Hello, World"
(영구 설정은 .zshrc 내 할 것)head
: 파일 첫 라인 출력 | head -n 10
제외 가능 head -10
tail
: 파일 끝 라인 출력 | tail -n 10
혹은 실시간 로그 조회 시 tail -f -n 10
(10번째부터)tail -f /var/log/apache2/access.log
tail -f /var/log/nginx/access.log
tail -f /usr/local/var/log/nginx/access.log
tail -f /var/log/tomcat/access.log
/ catalina.out
exec
라는 시스템 콜 함수를 통해 fork
가 발생$ls | sort | less
= ls 명령어 수행 후 그 결과 기반으로 → sort 명령어 수행 후 그 결과 기반으로 → less 명령어 수행
$ls -l | grep key | less
= 또 다른 예시
grep
: 문자열 중 특정 정규표현식 조건 검색 | 위에서 tail
통한 실시간 로그 조회 중 원하는것만 조회 시
tail -f /usr/local/var/log/nginx/access.log | grep favicon.ico
tail -f /usr/local/var/log/nginx/access.log | grep **-E** "127.0.0.1"
(정규표현식)tail -f /usr/local/var/log/nginx/access.log | **egrep** "127.0.0.1"
(정규표현식)-E
: 정규표현식 사용을 위해서는-i
: 대소문자 구분없는 검색을 위해서는-n
: 검색된 라인 넘버 표기-A 10
혹은 -B 10
, -C 10
: 해당 검색된 라인의 앞과 뒤에 50라인씩 추가로 출력해보는 것 추천pbcopy
: 클립보드에 복사하기 (매번 마우스로 드래그 복사 X) | 윈도우에서는 clip
명령어를 사용pbcopy < ~/.gitignore_global
| 윈도우에서는 clip < ~/.gitignore_global
pbcopy < .ssh/id_rsa.pub
| 윈도우에서는 clip < ~/.gitignore_global
cat ~/.gitignore_global | pbcopy
| 윈도우에서는 cat ~/.gitignore_global | cliip
cat ~/.gitignore_global | pbcopy
와 pbcopy < ~/.gitignore_global
는 사실상 같은 역할을 하나, Override 를 잘못 사용했다가는 큰일 날 수 있기에 후자를 권장echo
복습 : echo "Hello, World!" >> example.txt
cat
복습 : cat example.txt > copy.txt
&&
: 독립적으로 개별 수행 (|
파이프와 달리 앞 명령어 결과가 다음 명령어의 입력으로 들어가지 않음);
: 앞 명령어가 실패해도, 다음 명령어 실행 (&&
보다 완화된 연결)&
: 앞 명령어와 다음 명령어 동시실행||
: 앞 명령어가 실패하면, 다음 명령어 실행chmod
: 파일 권한 → 4 (READ) + 2 (WRITE) + 1 (EXECUTE) | 대상 : Owner + Group + Otherchmod **700** executable.sh
= Owner 에게 4(READ) + 2(WRITE) + 1(EXECUTE) 권한 추가chmod **+rwx** all-allow.sh
= chmod a**+rwx** all-allow.sh
= chmod **777** all-allow.sh
chmod **u+rwx** executable.sh
= chmod **700** executable.sh
u
: userg
: groupo
: othersa
: allchmod **400** readable.sh
chmod **500** excutable.sh
= Owner 에게 4(READ) + 1(EXECUTE) 권한 추가tar
: TAR 로 압축된 파일 풀기 | tar -xvf apache-tomcat-9.0.16.tar
-x
: extract 압축풀기 ↔ -c
: create 압축하기-v
: verbose 어떤 파일이 풀리는지 상세히보기-f
: filename 지정sudo
: superuser, 3개의 유저 (Root, User, Guest) 중 Root 권한 실행 | su root
권한 얻기, switchvi
: 텍스트 에디터 ↔ code
: VSCode 에디터협업 관리에 사용되는 툴로는 Github 뿐만아니라 Gitlab, Bitbucket, Gerrit 등이 존재
중앙 원격 Remote 은 V3 까지 정보가 적재되어있지만, 타인 Local A(빨간색) + 타인 Local B(파란색)은 각자 버전의 V4 존재
Git 설정이 정상적으로 된 경우 .git
디렉토리를 확인할 수 있다 → .git
을 어디서부터 생성하여 시작할까?
Local 인 Git 에서 먼저 .git
을 생성할지, Remote 인 Github 에서 먼저 .git
을 생성할지 결정이 필요하다
git push
git clone
Git 이 활성화되어 있는가? = .git
디렉토리가 생성되어 있는가?
.git
디렉토리 내 우리의 코드 작업을 추적하기위해 사용되는 모든 세부 디렉토리들이 존재한다.⛔ 어? 저 Git 이 이상해요..
- Spring 프로젝트가 아닌 Spring 프로젝트의 상위 디렉토리에
git init
(.git
디렉토리 생성)- 프로젝트 내 이미
git init
으로.git
디렉토리가 생겼는데, 프로젝트 안에서 또git init
>
Github 은 Remote 와 Local 간 보안 통신 방법으로 2가지 방식을 제시한다 : HTTPS & SSH
ssh-keygen -t ed25519 -C "name@example.com"
: SSH 키 생성기로 비공개/공개키 생성
SSH 을 위한 키 생성이 완료되면 ~/.ssh
디렉토리 안에 Private/Public Key 페어가 잘 생성된걸 볼 수 있다.
id_ed255519
) — Github : 공개키 (id_ed255519.**pub**
) ← 이걸 등록cat id_ed255519.**pub** | **pbcopy**
cat id_ed255519.**pub** | **clip**
Local(Git) 내 Git 초기 설정 후 → Remote(Github) 내 새 Repository 에 Push
git init
으로 Git 초기 설정 후git init
: 현재 내 디렉토리를 Git 으로 관리하겠다는것을 선언 = .git
디렉토리 생성실습 : 1. 로컬에서부터 Github 시작하기 - 명령어 호출 순서
git init
: 현재 작업중인 프로젝트를 Git 으로 관리하겠다는 선언git branch -M main
: 디폴트 브랜치 명칭 변경 ← master 가 아닌 main 이라는 비차별 명칭git remote add origin git@github.com:aaron/example.git
git push -u origin main
: Github Repository 타겟에 발사 = Pushgit remote -v
: 5번에서 앞서 추가한 원격 Github Repository 주소가 표기되는걸 확인Remote(Github)에서 새 Repository 생성 후 → Local(Git)에 Clone 으로 가져오기
Remote(Github) 에 새 Repository 생성 후
git init
을 통해 Git 설정 뒤 Remote 에 업로드한 경우Local(Git)에서 git clone
을 통해 Remote(Github) 에 있는 소스 코드 가져오기
실습 : 2. 원격에서부터 Github 시작하기 - 앞서 커밋 후 PUSH 한 결과물을 로컬로 가져와 진행
원격 Github Repository 에서 프로젝트를 새로 생성하여 진행해도 무방
git **clone**
git clone git@github.com:aaron/example.git
.git
디렉토리 생성.git
디렉토리도 확인 가능 = git 활성화echo 'local-v2' > README.md
: README 내 내용 추가 + git status
: 확인git commit -m "Local 2: second commit"
: Commit 메세지 입력 (다른거 해도됨)git log
혹은 git log --pretty=oneline
: 방금한 Commit 을 확인git push -u origin main
: 이미 앞서 Clone 을 통해 설정되어있는 타겟에 발사 = Push남의 코드를 어디서 다운로드할것인가, 나의 코드를 어디로 업로드할것인가
git remote -**v**
→ -**v** = **v**erbose
: 상세 출력 (verbose : 말많은, 상세한, 구구절절)git remote **add** **origin** git@github.com:aaron/example.git
origin
: Alias 별명, 별칭 → 위의 스크린샷 예시에선 aaron
이라고 설정되어있음git@github.com:aaron/example.git
: 원격 주소 = Github Repository 주소https://github.com/aaronryu/5th-git-from-local.git
git@github.com:aaronryu/5th-git-from-local.git
git remote **set-url** **origin** git@github.com:aaron/example.git
git remote **set-url --push origin** git@github.com:aaron/example.git
git remote **remove** **origin**
로컬에서의 명령어를 통해 → 원격 Remote 브랜치 & 로컬 Local 브랜치 모두 관리
Git 에서는 기능별로 혹은 개발하는 개발자별로 다수의 Branch 로 구성 가능
git fetch -**p**
→ -**p** = **p**rune
git branch -**r**
→ -**r** = **r**emote
: 원격 Remote Branch 조회git branch -**l**
→ -**l** = **l**ocal
: 로컬 Local Branch 조회git branch -**a**
→ -**a** = **a**ll
: 원격 Remote + 로컬 Local Branch 모두 전체 조회git checkout **-b** **example-branch**
→ -**b** = new-**b**ranch
git branch --**delete**/-**D** **example-branch**
: 로컬 Local Branch 삭제--**delete**
: 삭제 (현재 브랜치가 어디에도 머지되지 못했다면 경고와 함께 미삭제)-**D**
: 강제 삭제git push --**delete** **origin** **example-branch**
: 원격 Remote Branch 삭제origin
: 원격 주소(Github Repository 주소)에 대한 Alias 별명, 별칭example-branch
: 삭제하고자하는 브랜치명
- 실습 : 원격에서 브랜치 생성 및 삭제를 하며, 로컬과 원격 브랜치들이 어떻게 바뀌는지 조회
- 앞서서 로컬에서 or 원격에서 Github 시작하기가 끝이 난 후 |
git branch -a
통한 조회- 원격 Github 에서 브랜치를 생성하고, 로컬에서
git fetch
수행 |git branch -l
통한 조회
- 앞선 실습에서 로컬에서 Commit 총 2개를 했었는데, 이번엔 원격에서 Commit 1개 생성
- 커밋 메세지는
"Remote 1: third commit"
으로 하여 원격에서한 커밋임을 명시git branch -a
: 원격에서 추가한 브랜치를 PULL 받기전엔 새 브랜치를 인지하지 못함git fetch
: 원격에 있는 최신 브랜치 정보들을 로컬 내 Remote 의 Reference 로 가져옴git branch -a
: 원격에서 추가된 새 브랜치가 로컬의 브랜치 정보에 모두 다 싱크- 원격 Github 에서 브랜치를 삭제하고, 로컬에서
git fetch
수행 → 아무일도 일어나지 않음
git branch -a
조회 시, 원격에선 삭제된 브랜치이나 로컬에선 여전히 브랜치 레퍼 존재- 다시, 로컬에서
git fetch -**p**
수행 시 모든걸 싱크 =-**p** = **p**rune
옵션이 갖는 의미 확인하기
- 3번에서 삭제된 원격 Github 의 브랜치가 → 로컬 브랜치를 삭제하며, 삭제된 브랜치가 동기화 >
- 실습 : 로컬에서 기존의 로컬 브랜치를 삭제하거나 기존의 원격 브랜치를 삭제
- 앞서 생성한
feature/1
브랜치 로컬에서 삭제 :git branch **--delete** feature/1
- 새 커밋이 존재하나 어디도 머지되지 않았을때 삭제 거부 시 :
git branch **-D** feature/1
- 앞서 생성한
feature/1
브랜치 원격에도 삭제 :git push **--delete** origin feature/1
>
- 실습 : 로컬에서 새 브랜치를 생성하고 원격으로 푸시한 다음 기존의 브랜치와 머지 = 합침
1. 2가지의 브랜치(main
,sub
)가 있는 상황에서main
과sub
에서 시작하는것의 차이
-main
: 최초 Commit 1개 ⇒ 여기서 시작할래?
-sub
: 최초 Commit 1개 + 추가 Commit 1개 ⇒ 여기서 시작할래?
2. 두 브랜치 각자마다에서 새 브랜치 만들기main
,sub
후 그 차이를 원격/로컬에서 확인
-advanced-main
: 기존 최초 Commit 1개 + 새 Commit 1개
-advanced-sub
: 기존 최초 Commit 1개 + 추가 Commit 1개 + 새 Commit 1개
- 주의 : 디렉토리 기반으로 히스토리를 적재하기에 브랜치명에 계층이 있어서는 안된다.
- 예를 들어서main/advanced
dsub/advanced
3. 앞서 만든 브랜치 중advanced-main
브랜치main
브랜치에 Pull Request 요청
4. 앞서 만든 브랜치 중advanced-sub
필요가 없어져서 삭제한 후 Push 를 통해 삭제 >
git fetch -**p**
→ -**p** = **p**rune
branch
의 최신 코드를 로컬에 있던 branch
의 구식 코드에 합치기git merge **FETCH_HEAD**
remotes/origin/**HEAD** -> origin/**main**
= 원격 기본 브랜치git clone
하여 가져왔을때 표기할 기본 브랜치 (예, main)충돌 시나리오 2 : Push 받을때 충돌 Conflict 발생 (Github 이 알려줌) = V3 과 V3 모두 V2 라는 같은 기준 위에 작업 수행
어떻게 해결할 수 있는가? 2가지의 Conflict 충돌 해결방법
remote: Enumerating objects: 4, done.
remote: Counting objects: 100% (4/4), done.
remote: Compressing objects: 100% (3/3), done.
remote: Total 4 (delta 1), reused 4 (delta 1), pack-reused 0 (from 0)
Unpacking objects: 100% (4/4), 1.69 KiB | 432.00 KiB/s, done.
From github.com:6th-asac/html-and-js-review
* branch main -> FETCH_HEAD
* [new branch] main -> origin/main
hint: You have divergent branches and need to specify how to reconcil them.
hint: You can do so by running one of the following commands sometime before
hint: your next pull:
hint:
hint: git config pull.rebase false # merge (the default strategy)
hint: git config pull.rebase true # rebase
hint: git config pull.ff only # fast-forward only
hint:
hint: You can replace "git config" with "git config --global" to set a default
hint: preference for all repositories. You can also pass --rebase, --no-rebase,
hint: or --ff-only on the command line to override the configured default per
hint: invocation.
fetal: Need to specify how to reconcile divergent branches
hint: git config pull.ff true # merge (fast-forwarded if possible)
hint: git config pull.ff false # merge (never fast-fowarded)
hint: git config pull.ff only # fast-forward only
git -v
- 실습 : (A) 같은 브랜치
advanced-main
에서 [ 원격 브랜치 - 로컬 브랜치 ] 충돌
- 앞서 오류없이 머지했던
advanced-main
브랜치에 대한 작업을 원격 - 로컬 양쪽에서 작업
- 원격에서
advanced-main
브랜치에 커밋"Remote 2: fourth commit"
추가- 로컬에서
advanced-main
브랜치에 커밋"Local 3: fifth commit"
추가- 원격
advanced-main
브랜치에 로컬advanced-main
브랜치를 Push 시 머지 충돌 발생- 어떻게 머지 충돌을 해결해야할까 : 나중에 할 수업이지만 당장은 Pull 받아 머지 커밋 생성 후 Push >
- 실습 : (B) 다른 브랜치
advanced-main
-main
간 = [ 원격 브랜치 - 원격 브랜치 ] 충돌
1. 원격main
브랜치에 커밋"Remote 3: sixth commit"
추가
2. (방금 작업했던) 원격advanced-main
브랜치를 원격main
브랜치에 Pull Request 발행
3. 원격advanced-main
브랜치를 원격main
브랜치에 머지 시 충돌 발생
4. 어떻게 머지 충돌을 해결해야할까 : 나중에 할 수업이지만 당장은 아래와 같이 해결
- 로컬
advanced-main
브랜치에서 원격main
브랜치를 Pull 받아 머지 커밋 생성 후 Push- 다시 원격
advanced-main
브랜치를 원격main
브랜치에 머지 시 성공 >
- Rebase 단점 : 내가 작업했던 커밋들이 다시 생성되기에, 히스토리가 리셋
- Merge 단점 : 머지 커밋이 덕지덕지 생성되어서 머지 수가 많아짐에 따라 커밋 로그들이 더러워짐
⛔ Merge 에서 Conflict 발생 시, 대부분 패닉에 빠지는데
Merge 롤백 :
git merge --abort
--ff
(DEFAULT) : 로컬에 어떠한 작업도 없을때 원격 FETCH_HEAD 을 로컬 HEAD 로git fetch
+ git merge origin/main
혹은 git merge **--ff** origin/main
(충돌)git config pull.**ff** **only**
(주의 : Fast-Forward 가 아니면 Pull 자체가 안되게 강제)git pull **--ff-only** origin main
(Fast-Forward 가 불가능할 경우 거절됨)실습 : Fast-Foward 실습
main
브랜치에서도 추가 커밋 + 로컬 main
브랜치에서도 추가 커밋아래와 같이 로컬 main
브랜치를 → 원격 main
브랜치로 Push 한다면 머지 충돌 발생
> git push
To github.com: 2SEONGA/git-asac-7th.git
! [rejected]
main -> main (non-fast-forward)
error: failed to push some refs to 'github.com: 2SEONGA/git-asac-7th.git'
hint: Updates were rejected because the tip of your current branch is behind
hint: its remote counterpart. Integrate the remote changes (e.g.
hint: 'git pull ...') before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.
git pull **--ff-only** origin main
수행git fetch
+ git merge origin/main
혹은 git merge **--ff** origin/main
> git pull --ff-only origin main
remote: Enumerating objects: 5, done.
remote: Counting objects: 100% (5/5), done.
remote: Compressing objects: 100% (2/2), done.
renote: Total 3 (delta 1), reused O (delta O), packreused O (from 0)
Unpacking objects: 100% (3/3), 915 bytes | 228.00 KiB/s, done.
From github.com:aaronryu/hello-project
* branch main -> FETCH_HEAD
eb7939a..905faa6 main -> origin/main
hint: Diverging branches can't be fast-forwarded, you need to either :
hint:
hint: git merge - -no-ff
hint:
hint: or :
hint:
hint: git rebase
hint:
hint: Disable this message with "git config advice.diverging false"
fital : Not possible to fast-forwarf, aborting.
> git merge origin/main
Updating 713704a..a646151
Fast-forward
README.md | 3 +++
1 file changed, 3 insertions(+)
--ff-only
옵션의 경우엔 : Fast-Forward 조건에 맞지 않으면 → 동작되지 않지만> git pull --ff-only ****origin main
From github.com:2SEONGA/git-asac-7th.git
* branch main -> FETCH_HEAD
hint: Diverging branches can't be fast-forwarded, you need to either:
hint:
hint: git merge - -no-ff
hint:
hint: or:
hint:
hint: git rebase
hint:
hint: Disable this message with "git config advice.diverging false"
fatal: Not possible to fast-forward, aborting.
--ff
옵션의 경우엔 : Fast-Forward 조건에 맞지 않으면 → --no-ff
로 동작> git pull --ff-only ****origin main
Auto-merging README.md
CONFLICT (content): Merge conflict in README.md
Automatic merge failed; fix conflicts and then commit the result.
--no-ff
: 원격 FETCH_HEAD 와 HEAD 를 합친 새 Merge Commit 생성git fetch
+ git merge **--no-ff** origin/main
git config pull.**rebase** **false**
(DEFAULT)git pull origin main
실습 : 3-Way Merge 실습
main
브랜치에서도 추가 커밋 + 로컬 main
브랜치에서도 추가 커밋main
브랜치를 → 원격 main
브랜치로 Push 한다면 머지 충돌 발생> git push
To github.com: 2SEONGA/git-asac-7th.git
! [rejected] main -> main (non-fast-forward)
error: failed to push some refs to 'github.com: 2SEONGA/git-asac-7th.git'
hint: Updates were rejected because the tip of your current branch is behind
hint: its remote counterpart. Integrate the remote changes (e.g.
hint: 'git pull ...') before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.
git pull origin main
수행 = 바로 3-Way Merge 시도git fetch
+ git merge **--no-ff** origin/main
> git pull origin main
From github.com: 2SEONGA/git-asac-7th.git
* branch main -> FETCH_HEAD
Auto-merging README.md
CONFLICT (content): Merge conflict in README.md
Automatic merge failed; fix conflicts and then commit the result.
> git status
On branch main
Your branch and 'origin/main' have diverged,
and have 1 and 3 different commits each, respectively.
(use "git pull" to merge the remote branch into yours)
You have unmerged paths.
(fix conflicts and run "git commit")
(use "git merge --abort" to abort the merge)
Unmerged paths:
(use "git add < file>..." to mark resolution)
both modified: README. md
no changes added to commit (use "git add" and/or "git commit -a")
git fetch
+ git **rebase** origin/main
git config pull.**rebase** **true**
git pull **--rebase** origin main
(Rebase 가 불가능할 경우 거절됨)> git pull --rebase origin main
From github.com: 2SEONGA/git-asac-7th.git
* branch main -> FETCH_HEAD
Auto-merging README.md
error: could not apply 05cb233... Local 7
hint: Resolve all conflicts manually, mark them as resolved with
hint: "git add/rm <conflicted_files>" , then run "git rebase --continue"
hint: You can instead skip this commit: run "git rebase --skip".
hint: To abort and get back to the state before "git rebase", run "git rebase - abort"
Could not apply 05cb233... Local 7
수업 실습 : Rebase 실습
main
브랜치에서도 추가 커밋 + 로컬 main
브랜치에서도 추가 커밋main
브랜치를 → 원격 main
브랜치로 Push 한다면 머지 충돌 발생> git push
To github.com: 2SEONGA/git-asac-7th.git
! [rejected] main -> main (non-fast-forward)
error: failed to push some refs to 'github.com: 2SEONGA/git-asac-7th.git'
hint: Updates were rejected because the tip of your current branch is behind
hint: its remote counterpart. Integrate the remote changes (e.g.
hint: 'git pull ...') before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.
git pull **--rebase** origin main
수행 = 바로 Rebase 시도git fetch
+ git **rebase** origin/main
> git pull -- rebase origin main
From github.com: 2SEONGA/git-asac-7th.git
* branch main -> FETCH_HEAD
Auto-merging README. md
CONFLICT (content): Merge conflict in README. md
error: could not apply 05cb233... Local 7
hint: Resolve all conflicts manually, mark them as resolved with
hint: "git add/rm ‹conflicted files>" , then run "git rebase --continue".
hint: You can instead skip this commit: run "git rebase --skip"
hint: To abort and get back to the state before "git rebase", run "git rebase
abort".
Could not apply 05cb233.. Local 7
git fetch
+ git merge **--squash** origin/main
git checkout
git commit
.gitconfig
excludesfile = /Users/**aaron**/.gitignore_global
내부에는 DS_Store 방지 | 명칭 바꿀것
```
.DS_Store
._.DS_Store
**/.DS_Store
**/._.DS_Store
```
# ------- Default User Set --------
[user]
name = Aaron Ryu
email = fbcndah@gmail.com
initials = aaron
[http]
sslVerify = true
[core]
autocrlf = input
whitespace= fix,-indent-with-non-tab,trailing-space,cr-at-eol
fscache = true
editor = vi
excludesfile = /Users/aaron/.gitignore_global
# ------- Merge Tool --------
[merge]
tool = vscode
[mergetool "vscode"]
trustExitCode = false
[diff]
tool = vscode
[difftool "vscode"]
cmd = code --wait --diff $LOCAL $REMOTE
# ------- Alias --------
[alias]
co = checkout
ci = commit
st = status
br = branch
; ? = diff
l = !git graph | less -FXRS
r = !git graph -20 | less -FXRS
h = !git graph -1 | less -FXRS
graph = log --graph --date-order -C -M --pretty=format:\"%C(blue)%h%C(reset) (%ar) [%an] %C(yellow)%d%Creset %s\" --all --date=short
ls = log --graph -C -M --pretty=format:"%C(yellow)%h%Cgreen%d\\ %Creset%s%Cblue\\ [%cn]" --decorate --all --date=short
ll = log --pretty=format:"%C(yellow)%h%Cgreen%d\\ %Creset%s%Cblue\\ [%cn]" --decorate --all --numstat
del = "!f() { git branch -d \"$1\" && git push origin --delete $1; }; f"
.gitconfig
# ------- Default User Set --------
[user]
name = Aaron Ryu
email = fbcndah@gmail.com
initials = aaron
# name = Kim Doyeon
# email = doyeon311@gmail.com
# initials = kimdoyeonn
[http]
sslVerify = true
[core]
autocrlf = input
; if true, git considers that 'CR' is added,
; when 'CRLF' in working directory --> 'LF' in Repo
; safecrlf = true
; when [autocrlf = false] git reject commit
; - Commit: CRLF -> LF
; - Checkout: LF -> CRLF
; Consume there is only 'LF' in repository
whitespace= fix,-indent-with-non-tab,trailing-space,cr-at-eol
; preloadindex = true [default]
fscache = true
editor = vi
excludesfile = /Users/aaron/.gitignore_global
# ------- Colors --------
[color]
; ui = true [default]
; interactive = true [default]
[color "diff"]
; meta = blue white bold
# ------- Merge Tool --------
[merge]
tool = vscode
[mergetool "vscode"]
trustExitCode = false
[diff]
tool = vscode
[difftool "vscode"]
cmd = code --wait --diff $LOCAL $REMOTE
# ------- Alias --------
[alias]
co = checkout
ci = commit
st = status
br = branch
; ? = diff
l = !git graph | less -FXRS
r = !git graph -20 | less -FXRS
h = !git graph -1 | less -FXRS
graph = log --graph --date-order -C -M --pretty=format:\"%C(blue)%h%C(reset) (%ar) [%an] %C(yellow)%d%Creset %s\" --all --date=short
ls = log --graph -C -M --pretty=format:"%C(yellow)%h%Cgreen%d\\ %Creset%s%Cblue\\ [%cn]" --decorate --all --date=short
ll = log --pretty=format:"%C(yellow)%h%Cgreen%d\\ %Creset%s%Cblue\\ [%cn]" --decorate --all --numstat
; standup = log --since yesterday --oneline --author <who@you-want-to-know.com>
del = "!f() { git branch -d \"$1\" && git push origin --delete $1; }; f"
# ------- Additional --------
[heroku]
account = work
; Cloud PaaS like AWS, give us 1 Free host
[gitopen "gitlab"]
domain = http://my.own.page.net/project/
; git clone and add to ./zshrc
; git clone https://github.com/paulirish/git-open.git $ZSH_CUSTOM/plugins/git-open
git config --list
명령어를 통해 우리가 설정한 내용들이 잘 적용되어있는지 일괄 확인이 가능git init
: .git
생성 및 시작fatal: not a git repository (or any of the parent directories): .git
git fetch -p
: 원격 브랜치를 로컬로 가져오기 (원격-로컬 브랜치 동기화)git pull origin main
: 원격 main 브랜치의 최신 커밋들을 로컬로 가져오기 (Pull + Merge)git branch -a
: 원격 브랜치와 로컬 브랜치 리스트 조회실습 : 로컬 프로젝트에서 Git 활성화 후 새 원격 저장소에 Push → 새로운 브랜치 만들기
git clone
: 원격 저장소의 코드 = 브랜치들을 로컬로 가져오기git remote -v
: 원격 저장소 조회git fetch
: 원격 저장소에서 생성한 브랜치 조회git branch -a
: 생성된 브랜치 포함 모든 브랜치 조회 (원격 브랜치에 대한 Reference 확인)git fetch -p
: 원격 브랜치에서 삭제한 브랜치 조회git branch -a
: 삭제된 브랜치 포함 모든 브랜치 조회 (원격 브랜치에 대한 Reference 확인)git checkout -b [새 브랜치명]
: 새 로컬 브랜치 생성git branch -a
: 생성된 브랜치 포함 모든 브랜치 조회git checkout
: 로컬 브랜치 이동 - 다시main
브랜치로 돌아가기 >
git add [파일명]
: Git 커밋에 수정 사항으로 등록하기 위한 예비 절차 = Staged : Commit 대기 (예비)git add -p
: 파일 단위의 추가가 아닌 텍스트 단위의 추가 (아래에서 더 상세하게 사용법을 배울 것)git add .
: 변경된 파일 모두 추가 (생각보다 이것만 사용)실습 : 새 커밋 만드는 방법 = 새로운 파일 “추가하기” + 기존 파일 “수정하기”
touch README.md
: 새로운 파일 “추가하기”git status
+git add
: Untracked = Git 이 추적하지 않아서 처음보는 파일echo 'main' >> README.md
: 기존 파일 “수정하기”git status
+git add
: Unstaged → Staging = Git 이 추적하고있어 알고있는 파일touch hello-world.sh
+echo "echo 'Hello, World!'" > hello-world.sh
./hello-world.sh
: 실행이 되지 않는다 = Permission Denied 실행 권한이 없는것chmod 700 ./hello-world.sh
: 실행 권한을 부여해주자- 이 파일은 Git 내 포함시키고싶지 않다 = 하지만 계속 Untracked 로 보이는것이 걸리적거림
git status
:hello-world.sh
파일이 Untracked 로 보임 = 걸리적거림touch .gitignore
+echo '**/hello-world.sh' >> .gitignore
- * 두 개와 한 개의 차이?
- ** : 0개 이상의 디렉토리 및 모든 하위 디렉토리
- : 단일 디렉토리 또는 파일 이름에서 0개 이상의 문자와 일치
git status
:hello-world.sh
파일이 보이지않음 +.gitignore
가 Untracked 로 보임git add
+git commit
:.gitignore
파일을 Git 에 추가
git add -p
수행하려면 중간중간 작업물이 들어가야해서 시간이 걸림작업중에 잠깐 지금의 작업을 어딘가에 임시 저장하였다가, 나중에 다시 활용하고 싶을 때
git stash
: 현재 git add
를 통해 Commit 대기중인 모든 수정사항들 임시 저장소에 저장git stash pop
: 임시 저장소에 저장되어있는것중 가장 최신의 하나를 꺼냄 (Stack 자료구조)git stash list
: Stack 자료구조에 쌓여있는 임시 저장본 리스트 조회실습 : 앞 실습서
main
브랜치로 돌아왔을텐데 작업하다 Stash 로feature/1
브랜치로 이동
- 변경사항이 별로 없을땐 단순
git checkout
만으로도 바로 이동가능하나 보편적 케이스는 아님- 파일을 수정했을때 Unstaged →
git stash
: 스태싱 O = 변경사항이기 때문- 파일을 추가했을때 Untracked →
git stash
: 스태싱 X = 변경사항이 아니기 때문
git commit
: 에디터를 통해 메세지 입력하여 커밋 (일반적으로는 vi
사용, 커스텀 시 code
사용 가능)git commit -m "메세지"
: 입력한 메세지를 통해 (귀찮게 에디터 켜지 않고) 바로 커밋git commit -am "메세지"
: git commit -a
(Untracked 제외) + git commit -m "메세지"
git commit --amend
: 앞선 커밋 수정 (커밋 메세지 수정 or 커밋 내용 추가)git push
: 현재 브랜치에 커밋된 내용 모두 원격에 업로드(푸시)git push -u origin main
: 로컬 브랜치에 연결된 원격 브랜치가 없을때 최초 연결git push --set-upstream-to origin main
실습 : 앞 실습서
main
브랜치로 돌아왔을텐데 작업하다 Stash 로feature/1
브랜치로 이동
- 파일을 수정했을때 Unstaged →
git commit -am
시 적용 : 커밋되는것을 확인 가능- 파일을 추가했을때 Untracked →
git commit -am
시 미적용 : 커밋되지 않는것을 확인 가능
실습 : 직전 단일 커밋을 수정해야할때
git commit **--amend**
1. 커밋 메시지 수정 케이스
2. 커밋에 넣어야하는데 놓친 수정 내용을 기존 커밋에 합치는 케이스
git reset HEAD~1
: 현재 커밋 Mixed 롤백 = 커밋했던 수정본 모두 다시 커밋되지 않은 상태로 롤백git reset --hard HEAD~1
: 현재 커밋 Hard 롤백 = 커밋했던 수정본 (흔적도 없이) 싹다 없애고 롤백2cd27c2427c904c6ec4d30ce28a633e4d5113245f
HEAD~1
혹은 HEAD^1
실습 : 이전 다수 커밋을 롤백해야할때 =
git **reset**
git reset **--hard** HEAD~1
: 아예 흔적까지 없애버리는것 = 싹 다 롤백git reset **--mixed** HEAD~1
=git reset HEAD~1
(Default) : 작업물 그대로 남긴채 롤백git reset **--soft** HEAD~1
: 작업물 그대로 남긴채 롤백 (Staging = 바로 커밋 가능)
git log
: 커밋 메세지 기반 조회git show
: 커밋 메세지 + 상세 수정내용 기반 조회윈도우 : git config --global core.**autocrlf** **true**
리눅스 : git config --global core.**autocrlf** **input**
warning: in the working copy of 'detail.html', LF will be replaced by CRLF the next time Git touches it.
warning: in the working copy of 'simple.html', LF will be replaced by CRLF the next time Git touches it.
git checkout
new file:
+ (2) modified:
+ (3) deleted:
git commit
명령어 시 여기에 있는 파일들이 Commit 된다 (스냅샷 찍힘)modified:
+ (3) deleted:
git add
new file:
git add
.gitignore
에 추가git **add** <file>
: 변경된 파일 하나만 지목하여 Staging Area 로 전달git **add** .
: 모든 파일 변경 사항들을 한번에 Staging Area 로 전달git **add** -p
: 모든 파일 변경 사항들을 작은 단위로 세부적으로 확인하며 Staging Area 로 전달git **restore --staged** <file>
: Staging Area → Unstaged (git add
이전)git **restore** <file>
: Unstaged → (Unmodifed) (수정 이전)실습 : 파일 수정 시나리오 = Unstaged ↔ Staging
echo 'example' >> README.md
: 기존 Git 이 추적하고있는 파일의 수정 = Unstagedgit add README.md
: Commit 을 위한 대기조 = Staging ← Unstagedgit restore --staged README.md
: Commit 대기조에서 제외 = Staging → Unstagedgit add README.md
: Commit 을 위한 대기조 = Staging ← Unstaged (이해를 위한 반복)git restore --staged README.md
: Commit 대기조에서 제외 = Staging → Unstagedgit restore README.md
: 해당 파일의 수정된 내용을 Git 이 추적하는 이전 스냅샷으로 롤백
- Unstaged 의미는 Git 이 추적하는 파일의 이전 스냅샷에서 바뀌었다는것이므로
- 본
restore
명령어를 통해 이전 스냅샷으로 돌아간다는 것 = 현재 수정 내용을 롤백한다는 것
.gitignore
내 등록 : 민감 정보 등git **add**
를 통해 Staging Area 로 전달git **restore --staged** <file>
: Staging Area → Untracked (git add
이전)실습 : 파일 추가 시나리오 = Untracked ↔ Staging
touch example
: 기존 Git 이 추적하고있지 않은 파일의 추가 = Untrackedgit add example
: Commit 을 위한 대기조 = Staging ← Untrackedgit restore --staged README.md
: Commit 대기조에서 제외 = Staging → Untrackedgit add example
: Commit 을 위한 대기조 = Staging ← Untracked (이해를 위한 반복)git restore --staged README.md
: Commit 대기조에서 제외 = Staging → Untrackedgit add example
+git commit
: 바로 아래에서 파일 삭제 시나리오 실습을 위해 Commit
git **rm** <file>
git **rm --cached** <file>
실습 : 파일 삭제 시나리오 = Unstaged ↔ Staging ↔ Untracked
rm example
: 기존 Git 이 추적하고있는 파일의 삭제 = Unstagedgit add example
: Commit 을 위한 대기조 = Staging ← Unstagedgit restore --staged README.md
: Commit 대기조에서 제외 = Staging → Unstagedgit add example
: Commit 을 위한 대기조 = Staging ← Untracked (이해를 위한 반복)git restore --staged README.md
: Commit 대기조에서 제외 = Staging → Untrackedgit restore example
: 해당 파일이 삭제된 것을 Git 이 추적하는 이전 스냅샷으로 롤백
- Unstaged 의미는 Git 이 추적하는 파일의 이전 스냅샷에서 바뀌었다는것이므로
- 본
restore
명령어를 통해 이전 스냅샷으로 돌아간다는것 = 현재 삭제된걸 롤백한다는것
git rm example
: 기존 Git 이 추적하고있는 파일의 삭제 + Commit 대기조 = Staginggit rm --cached example
: 기존 Git 이 추적하고있는 파일의 삭제 + 개인적으로 파일 사용앞서 배우고 실습했던 내용들을 합치면 검은색 화살표 ↔ 주황색 화살표 이 2개가 서로 반대라는것만 알면됨
--staged
옵션에 따라 Staging Area 에서 롤백할지 Unstaged 에서 롤백할지 결정--staged
옵션이 있으면 : Staging Area 에서 롤백--staged
옵션이 없으면 : Unstaged 에서 롤백 (아무일도 없던것처럼 깨끗히 롤백)[ASAC-001] 테스트 코드 작성을 위한 준비
(선택) 그 아래엔 어떤 세부 작업이 있는지 나열하는 것 추천 → 구체적일 필요는 없으나 언제봐도 알 수 있게
[HELLO-001] 테스트 코드 작성을 위한 준비
- 어떤어떤 작업을 수행
- 어떤어떤 값들을 추가하여 어떤어떤 작업을 도움
- 어떤어떤 값을 변경
Feat: 테스트 코드 작성을 위한 준비
git commit --amend
git reset HEAD~1
git reset **HEAD~3**
: 3번째 전으로 3개의 커밋 모두 롤백--soft
: Staging Area--mixed
(Default) : Unstaged/Untracked--hard
: 완전히 없애는것git rebase -i HEAD~3
git reflog
git reflog
통해 이전에 수행했던 히스토리들을 쭉 살펴보고 원하는 커밋의 SHA 해시값을 봤으면git reset --hard 349b40d
git checkout -b backup 349b40d
개발 결과물 테스트를 위한 Develop Zone 과 실제 유저들이 사용하기 위해 배포하는 Production Zone
그리고 이러한 Zone 과 연동하여 관리하는 Git 브랜치 전략(git-flow)
부트캠프 혹은 학생들의 개인, 팀 프로젝트들은 Zone 구별없이, 로컬에서 테스트하거나 최종 배포하여 테스트
현업에서는 실제 유저 사용에 있어 문제가 발생하지 않도록 테스트를 꼼꼼히 진행하며, 문제 발생 시 롤백 전략
- Local : 실제 개발을 진행하며, 디버깅 및 로컬 테스트를 수행하는 로컬 환경
- Local 데이터베이스 : 가벼운 테스트를 위해 개발자가 직접 적재 혹은 로컬 실행을 통해 적재되는 정보
- 가끔은 개발자간 데이터베이스 내 데이터 일관성을 위해 Migration SQL 구문으로 주고 받음
- 원시적인 방법으로 CSV(Comma Seperated Value) 파일을 주고받을 순 있으나 파일 크키가 큼
- Localhost 웹 브라우저 를 통한 Frontend 테스트 (예, React 의 Hot Loader 활용한 실시간 디버깅)
- Localhost Postman 를 통한 Backend 테스트 (예, Spring 으로 개발한 API)
- Develop Zone : 마무리된 개발에서 누락된 테스트 케이스는 없을지, 내부 사용자(개발자)에게 노출(배포)
- Develop Zone 데이터베이스 : 테스트를 위해 개발자들이 직접 적재 혹은 테스트를 통해 적재되는 정보
- 로컬에서보다 적재된 데이터량이 많고, 개발자들이 테스트를 진행하여 더 다양한 유즈케이스 커버
- 개발자간 데이터를 주고받을 필요없이 마음껏 단일 Develop DB 에 적재 가능
- 로컬에서 개발을 완료했다는것 : 개발자 개인이 수행해볼 수 있는 최대한의 유즈케이스를 커버했다는 뜻
- 주의 : Develop Zone 에서 버그가 발생하고, 그곳에서 버그를 찾는걸 너무 당연하게 생각하지 말자
- 누군가가 먹을 수 있는 수준의 음식을 만들고 시음을 하지, 시음으로 맛을 찾아가지 않음
- 어쨌거나 로컬만이 세부 디버깅 및 로그 확인이 가능한 가장 투명한 디버깅 공간
- Frontend 입장 : 내가 만든 프론트엔드가 다양한 (개발자) 유저에 잘 표기될 지
- Backend 입장 : 내가 만든 API 가 백엔드, 프론트엔드가 실제 호출했을때 문제 없을 것인지
- Production Zone : 실제 유저가 사용하는 환경으로 개발 및 수정 등에 신중해야하며, 제약이 심하다.
- Production Zone 데이터베이스 : 실제 유저가 사용하는 운영 DB
- 데이터베이스에 대한 ALTER 명령어는 매우 신중해야한다. 리인덱싱 이슈 등
- 이상적으로는 백업 전략을 통해 치명적인 문제가 발생할 경우 돌아갈 DB 스냅샷이 필요
- 언제나 그렇듯 대체의 환경과 기업에서 이상적인 상황을 적용하지는 않는다. 현실과의 타협
- 개발과 테스트를 완료한 경우, 실제 유저들이 해당 기능을 사용할 수 있게 최종 배포를 해야함
- Staging Zone : 운영존에 가장 가까운 환경, 최종 배포전 네트워크 및 인프라 환경에 대한 마지막 테스트
- Staging Zone 데이터베이스 : 운영존과 가장 가까운 수준의 데이터량을 적재
- 일반적으로 Develop Zone 과 Production Zone 의 DB 에 적재된 데이터량의 편차가 심함
- 비유를 하자면 Develop Zone 데이터량이 100 이면, Production Zone 데이터량은 10000 이상
- 수많은 데이터를 직접 적재하기 힘들기 떄문에, 아래서 배울 운영존 DB 에서 동기화해옴
- 단, Sanitizing 이란것을 통해 개인정보들에 대해 난수화 - 개인정보보호 법적 보호
- 하나의 버그가 치명적인 상황(경제적 이슈)을 불러일으키는 거대 유저를 보유한 기업의 경우에 많이 구축
- 스타트업 혹은 중견기업에선 Staging Zone 이 없다. 혹은 있다하더라도 개인정보 보호가 미약할 것
- 비용의 문제 : 운영존과 비슷한 환경을 구성하기 위해 사용해아하는 AWS 비용은 운영만큼 듦
- Staging Zone 데이터베이스 : 운영존과 가장 가까운 수준의 데이터량을 적재
- 일반적으로 Develop Zone 과 Production Zone 의 DB 에 적재된 데이터량의 편차가 심함
- 비유를 하자면 Develop Zone 데이터량이 100 이면, Production Zone 데이터량은 10000 이상
- 수많은 데이터를 직접 적재하기 힘들기 떄문에, 아래서 배울 운영존 DB 에서 동기화해옴
- 단, Sanitizing 이란것을 통해 개인정보들에 대해 난수화 - 개인정보보호 법적 보호
- 하나의 버그가 치명적인 상황(경제적 이슈)을 불러일으키는 거대 유저를 보유한 기업의 경우에 많이 구축
- 스타트업 혹은 중견기업에선 Staging Zone 이 없다. 혹은 있다하더라도 개인정보 보호가 미약할 것
- 비용의 문제 : 운영존과 비슷한 환경을 구성하기 위해 사용해아하는 AWS 비용은 운영만큼
- Production Zone : 실제 유저가 사용하는 환경으로 개발 및 수정 등에 신중해야하며, 제약이 심함
- Production Zone 데이터베이스 : 실제 유저가 사용하는 운영 DB
- 데이터베이스에 대한 ALTER 명령어는 매우 신중해야한다. 리인덱싱 이슈 등
- 이상적으로는 백업 전략을 통해 치명적인 문제가 발생할 경우 돌아갈 DB 스냅샷이 필요
- 언제나 그렇듯 대체의 환경과 기업에서 이상적인 상황을 적용하지는 않고 현실과의 타협
- 개발과 테스트를 완료한 경우, 실제 유저들이 해당 기능을 사용할 수 있게 최종 배포를 해야함
원칙은 모든 배포는 격리된 브랜치에서 작업을 완료한 뒤 PR 를 통해 배포를 위한 브랜치에 머지해야한다.
중요도에 따라 3가지 타입의 브랜치로 나누어진다.
feature/**HELLO-001**
: 기획과 디자인에 따라 개발자에게 발행된 티켓으로 브랜치명feature/**login-with-oauth**
: 어떤 작업인지 바로 알 수 있도록, 기능 내용에 대한 요약 브랜치명aaron/**login-with-oauth**
: 브랜치명에 개발자 명을 붙여넣기도함