개발을 시작하며 모르는 것 투성이었다..
그때 알아본 것들을 노션 개인 페이지에 정리했었는데 이를 티스토리에 옮기기로 결심했다...!
근데 노션이 더 이쁜 거 같은데 노가다가 생각보다 많지만 다른 분들한테도 도움이 되었으면 좋겠다☺️
댓글 환영해요
개발을 시작하며 모르는 것 투성이었다..
그때 알아본 것들을 노션 개인 페이지에 정리했었는데 이를 티스토리에 옮기기로 결심했다...!
근데 노션이 더 이쁜 거 같은데 노가다가 생각보다 많지만 다른 분들한테도 도움이 되었으면 좋겠다☺️
댓글 환영해요
git clone <https://{github 계정}/submodule_parent.git>
git submodule add <https://{github 계정}/submodule_child.git>
submodule_parent
├── .git
│ ├── COMMIT_EDITMSG
│ ├── FETCH_HEAD
│ ├── HEAD
│ ├── ORIG_HEAD
│ ├── config
│ ├── description
│ ├── hooks
│ ├── index
│ ├── info
│ ├── logs
│ ├── modules
│ ├── objects
│ ├── packed-refs
│ └── refs
├── .gitmodules
├── README.md
└── submodule_child # child repository가 parent 안에 생성
├── .git
└── README.md
[submodule "submodule_child"]
path = submodule_child
url = <https://{github 계정}/submodule_child.git>
위처럼, 서브모듈을 생성하면 parent repository 아래에 child repository 폴더가 생성되고 .git 폴더가 각각 생성되었다.
그리고 parent repository의 .gitmodules
파일이 내부에 submodule에 대한 정보가 생성된다.
⇒ 아래에서 parent와 child repository의 branch를 맞출 수 있는데 .gitmodules
파일을 사용한다.
git diff
명령을 실행시키면 흥미로운 점을 발견할 수 있다.
submodule_child
디렉토리를 서브모듈로 취급하기 때문에 해당 디렉토리 아래의 파일 수정사항을 직접 추적하지 않는다.
submodule_child
디렉토리의 모드는 160000이다. Git에게 있어 160000 모드는 일반적인 파일이나 디렉토리가 아니라 특별하다는 의미다.git diff --submodule
git push origin main
git submodule init
git submodule update
--recurse-submodules
옵션을 붙인다.git clone --recurse-submodules ${parent 원격 git 주소}
❗️ 주의사항
서브모듈은 결국 2개의 repository를 사용하기 때문에 parent에서 child를 변경 시에도 child의 git 상태가 변경됩니다.
따라서 parent에서는 최신 child를 참조만 하는 방법을 권장합니다. (방법 3-1.)
(만약, child repository를 수정 및 commit 했을 시에 3-2 가이드 참조)
⚠️ child가 변경되었을 시에 parent를 push 할 수 없게 설정
만약 child의 변경사항을 child의 원격에 push 하지 않고 parent를 push 했다면 다른 사용자가 parent를 clone 했을 경우, child의 커밋을 불러올 수 없어 에러가 난다!
# 반드시 설정 후 작업할 것
git config push.recurseSubmodules check
# 설정 확인하기
git config -l | grep "push.recursesubmodules"
A. child repository에서 직접 업데이트
# child repository로 이동
cd submodule_child
# child repository로 이동시 에 git은 child repository를 따른다.
git fetch
git merge origin/main
git diff --submodule
명령으로 변경 및 추가된 commit을 확인할 수 있고, --submodule
옵션 없이 항상 확인하고 싶다면 아래 명령을 실행# 모두 parent repository 디렉토리 기준에서 실행
$ git config --global diff.submodule log
$ git diff
Submodule DbConnector c3f01dc..d0354fc:
> more efficient db routine
> better connection routine
B. parent repository에서 한 번에 업데이트하기 (fetch & merge)
# parent 디렉토리에서 실행
git submodule update --remote
git submodule update --remote
명령어를 실행하면 기본적으로 master
브랜치를 checkout 하고
업데이트를 수행한다.main
→ child: main
/ parent: develop
→ child: develop
main
으로 설정하기git config -f .gitmodules submodule.submodule_child.branch main
[submodule "submodule_child"]
path = submodule_child
url = <https://{github 계정}/submodule_child.git>
branch = main
즉, parent branch에 따라 .gitmodules 안의 submodule.branch 설정을 변경하면 parent와 child의 branch가 동일하게 설정된다.
‼️ 주의
아래의 설정은 git fetch 시의 branch를 설정할 뿐이다. 만약, parent: main
/ child: main
브랜치에서 작업 중, parent를 develop
으로 변경한다 가정하자.
그럼 parent: develop
/ child: main
상태가 되고 이때 git submodule update —remote
명령어를 실행하면 parent의 .gitmodules
설정에 따라 child는 develop
원격을 fetch하여 HEAD는 detached
상태(원격 develop 상태)가 된다.
develop
→ main
으로 변경develop
브랜치임을 확인git submodule update --remote
실행detached
develop
, fetch 받아온 곳은 main
이라 HEAD 상태가 원격 main
을 따라 detached
)git status
로 submodule 상태 확인git status
명령을 실행했을 때, 업데이트한 서브 모듈에 “new commits”가 있다는 걸 알 수 있다.$ submodule_parent git:(main) ✗ git status
On branch main
Your branch is up to date with 'origin/main'.
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: submodule_child (new commits)
no changes added to commit (use "git add" and/or "git commit -a")
status.submodulesummary
설정하기# git config status.submodulesummary를 설정하면 서브모듈의 변경사항을 간단히 보여준다.
$ submodule_parent git:(main) ✗ git config status.submodulesummary 1
$ submodule_parent git:(main) ✗ git status
On branch main
Your branch is up to date with 'origin/main'.
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: submodule_child (new commits)
Submodules changed but not updated:
* submodule_child 2a18eba...b569a3d (14):
> origin child repo에서 커밋
no changes added to commit (use "git add" and/or "git commit -a")
git submodule update
명령을 실행하면 서브모듈 로컬 저장소는 Detached HEAD
상태로 남는다.
git submodule update
명령을 실행했을 경우를 의미.Detached HEAD
상태로 서브모듈을 수정하면 이후 git submodule update
명령 실행 시 수정사항을 잃을 수 있다.
$ git checkout develop
Switched to branch 'develop'
# --merge 옵션을 붙인다.
git submodule update --remote --merge
$ submodule_parent git:(develop) ✗ git submodule update --remote --merge
remote: Enumerating objects: 8, done.
remote: Counting objects: 100% (8/8), done.
remote: Compressing objects: 100% (4/4), done.
remote: Total 4 (delta 2), reused 0 (delta 0), pack-reused 0
Unpacking objects: 100% (4/4), 573 bytes | 286.00 KiB/s, done.
From <https://{github url}/submodule_child>
b2fa00b..0c4a069 develop -> origin/develop
Updating b2fa00b..0c4a069
Fast-forward
index.js | 6 ++++++
1 file changed, 6 insertions(+)
Submodule path 'submodule_child': merged in '0c4a0698e091583be408434a04ab6ead44096bc6'
이제 child의 Upstream 저장소(원격)에 다른 사람이 Push한 상황에서 로컬 저장소를 수정한 경우 아래와 같이 2가지 케이스가 발생한다.
$ submodule_child git:(develop) vim test.js
$ submodule_child git:(develop) ✗ ll
total 32
-rw-r--r-- 1 krk224 staff 6.1K 3 7 15:05 README.md
-rw-r--r-- 1 krk224 staff 693B 3 8 14:25 index.js
-rw-r--r-- 1 krk224 staff 22B 3 8 14:28 test.js
$ submodule_child git:(develop) ✗ git add test.js
$ submodule_child git:(develop) ✗ git commit -m "원본 child repo commit"
[develop 293477a] 원본 child repo commit
1 file changed, 1 insertion(+)
create mode 100644 test.js
$ submodule_child git:(develop) git push
Enumerating objects: 4, done.
Counting objects: 100% (4/4), done.
Delta compression using up to 8 threads
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 361 bytes | 361.00 KiB/s, done.
Total 3 (delta 0), reused 0 (delta 0), pack-reused 0
remote:
remote: To create a merge request for develop, visit:
remote: <https://{github url}/submodule_child/-/merge_requests/new?merge_request%5Bsource_branch%5D=develop>
remote:
To <https://{github url}/submodule_child.git>
d43fbdc..293477a develop -> develop
$ submodule_child git:(develop)
$ submodule_parent git:(develop) ✗ cd submodule_child
$ submodule_child git:(develop) ✗ pwd
/Users/krk224/{dir}/submodule_parent/submodule_child
$ submodule_child git:(develop) vim test.js
$ submodule_child git:(develop) ✗ git add test.js
$ submodule_child git:(develop) ✗ git commit -m "parent에서 child commit"
[develop be91ada] parent에서 child commit
1 file changed, 1 insertion(+)
create mode 100644 test.js
$ submodule_child git:(develop)
git submodule update --remote
명령 수행
git submodule update --remote --merge
명령 수행하면 위와 같이 merge 되거나 충돌 사항을 알려준다.➜ submodule_child git:(develop) cd ..
➜ submodule_parent git:(develop) ✗ git submodule update --remote
remote: Enumerating objects: 8, done.
remote: Counting objects: 100% (8/8), done.
remote: Compressing objects: 100% (5/5), done.
remote: Total 6 (delta 2), reused 0 (delta 0), pack-reused 0
Unpacking objects: 100% (6/6), 676 bytes | 225.00 KiB/s, done.
From <https://{github url}/submodule_child>
0c4a069..293477a develop -> origin/develop
Submodule path 'submodule_child': checked out '293477a7bb6e9e229b33c4a1d6043850c017c7fc'
➜ submodule_parent git:(develop) ✗ cd submodule_child
➜ submodule_child git:(293477a) cat test.js
console.log('hello');
➜ submodule_child git:(293477a)
console.log(’hello’)
)하며 Detached HEAD
상태로 만든다. (293477a
)develop
브랜치에 저장되어 있기 때문에 checkout 으로 돌린 후 git pull
작업을 수행하면 merge 된다.➜ submodule_child git:(293477a) git checkout develop
Previous HEAD position was 293477a 원본 child repo commit
Switched to branch 'develop'
Your branch and 'origin/develop' have diverged,
and have 1 and 2 different commits each, respectively.
(use "git pull" to merge the remote branch into yours)
## 로컬 저장소의 상태로 test.js 전환
➜ submodule_child git:(develop) cat test.js
console.log('parent에서 child 수정');
## 원격과 merge... vscode에서 conflict 수정
➜ submodule_child git:(develop) git pull
Auto-merging test.js
CONFLICT (add/add): Merge conflict in test.js
Automatic merge failed; fix conflicts and then commit the result.
➜ submodule_child git:(develop) ✗ git commit
U test.js
error: Committing is not possible because you have unmerged files.
hint: Fix them up in the work tree, and then use 'git add/rm <file>'
hint: as appropriate to mark resolution and make a commit.
fatal: Exiting because of an unresolved conflict.
## 현재 성공적으로 merge된 것을 확인
➜ submodule_child git:(develop) ✗ cat test.js
console.log('parent에서 child 수정');
console.log('hello');
: 이번에는 child의 원격 저장소가 업데이트된 상황에서 로컬 저장소를 수정만 한 경우
## 위에서 parent 안의 child 수정 사항 받아오기
➜ submodule_child git:(develop) git pull
remote: Enumerating objects: 9, done.
remote: Counting objects: 100% (9/9), done.
remote: Compressing objects: 100% (5/5), done.
remote: Total 6 (delta 1), reused 0 (delta 0), pack-reused 0
Unpacking objects: 100% (6/6), 698 bytes | 174.00 KiB/s, done.
From <https://{github url}/submodule_child>
293477a..c513ef0 develop -> origin/develop
Updating 293477a..c513ef0
Fast-forward
test.js | 1 +
1 file changed, 1 insertion(+)
## update된 child repo 확인
➜ submodule_child git:(develop) cat test.js
console.log('parent에서 child 수정');
console.log('hello');
## 원본 child에서 test.js 수정 및 확인
➜ submodule_child git:(develop) vim test.js
➜ submodule_child git:(develop) ✗ cat test.js
console.log('parent에서 child 수정');
console.log('hello');
**console.log('2번째 case 원본 child repo 수정!');**
## 원격 child repo update
➜ submodule_child git:(develop) ✗ git add *
➜ submodule_child git:(develop) ✗ git commit -m "2번째 케이스를 위해 원본 child repo 수정"
[develop bcec2e8] 2번째 케이스를 위해 원본 child repo 수정
1 file changed, 2 insertions(+)
➜ submodule_child git:(develop) git push
Enumerating objects: 5, done.
Counting objects: 100% (5/5), done.
Delta compression using up to 8 threads
Compressing objects: 100% (3/3), done.
Writing objects: 100% (3/3), 406 bytes | 406.00 KiB/s, done.
Total 3 (delta 1), reused 0 (delta 0), pack-reused 0
remote:
remote: To create a merge request for develop, visit:
remote: <https://{github url}/submodule_child/-/merge_requests/new?merge_request%5Bsource_branch%5D=develop>
remote:
To <https://{github url}/submodule_child.git>
c513ef0..bcec2e8 develop -> develop
## 현재 test.js 상태 확인
➜ submodule_child git:(develop) cat test.js
console.log('parent에서 child 수정');
console.log('hello');
➜ submodule_child git:(develop) vim test.js
## 수정된 test.js 출력
➜ submodule_child git:(develop) ✗ cat test.js
console.log('parent에서 child 수정');
console.log('hello');
console.log('parent안에서 child repo 수정하고 commit은 안함!');
git submodule update --remote
명령 수행➜ submodule_child git:(develop) ✗ cd ..
➜ submodule_parent git:(develop) ✗ git submodule update --remote
remote: Enumerating objects: 5, done.
remote: Counting objects: 100% (5/5), done.
remote: Compressing objects: 100% (3/3), done.
remote: Total 3 (delta 1), reused 0 (delta 0), pack-reused 0
Unpacking objects: 100% (3/3), 386 bytes | 386.00 KiB/s, done.
From <https://{github url}/submodule_child>
c513ef0..bcec2e8 develop -> origin/develop
error: Your local changes to the following files would be overwritten by checkout:
test.js
Please commit your changes or stash them before you switch branches.
Aborting
fatal: Unable to checkout 'bcec2e87e6d061244aaf9dbcbbba183dae3c05b4' in submodule path 'submodule_child'
위 경우 변경사항이 commit되지 않아 Aborting
에러를 발생시켜 remote를 checkout 실패한다.
→ 따라서 변경사항을 원하는 원하는 브랜치에 커밋 후 merge하기
## 이제 다른 사용자가 parent 프로젝트를 clone 했을 때의 상황
➜ {dir} git clone <https://{github url}/submodule_parent.git>
Cloning into 'submodule_parent'...
remote: Enumerating objects: 25, done.
remote: Total 25 (delta 0), reused 0 (delta 0), pack-reused 25
Receiving objects: 100% (25/25), 5.55 KiB | 5.55 MiB/s, done.
Resolving deltas: 100% (8/8), done.
➜ {dir} cd submodule_parent
## 현재 유실된 commit은 develop 기준이기 때문에 develop으로 스위칭
➜ submodule_parent git:(main) git switch develop
branch 'develop' set up to track 'origin/develop'.
Switched to a new branch 'develop'
➜ submodule_parent git:(develop) git submodule init
Submodule 'submodule_child' (<https://{github url}/submodule_child.git>) registered for path 'submodule_child'
## fetch error 발생!
➜ submodule_parent git:(develop) git submodule update
Cloning into '/Users/{dir}/submodule_parent/submodule_child'...
fatal: remote error: upload-pack: not our ref 029280eb6bfcc723f8ba8f35d7bfbc3bf8a85c7e
fatal: Fetched in submodule path 'submodule_child', but it did not contain 029280eb6bfcc723f8ba8f35d7bfbc3bf8a85c7e. Direct fetching of that commit failed.
3-1에서도 표기했지만 다시 한번 강조!
⚠️ child가 변경되었을 시에 parent를 push할 수 없게 설정
만약 child의 변경사항을 child의 원격에 push하지 않고 parent를 push하고 다른 사용자가 parent를 clone했을 경우, child의 커밋을 불러올 수 없어 에러가 난다!
# 반드시 설정 후 작업할 것
git config push.recurseSubmodules check
# 설정 확인하기
git config -l | grep "push.recursesubmodules"
git config push.recurseSubmodules
옵션check
: child를 원격에 push하지 않은 경우, parent push 실패 처리on-demand
: child를 원격에 push하지 않은 경우, 자동으로 child push 후에 parent push 시도
🚨 중요!
토큰 자체에 사용자의 권한 정보나 서비스를 사용하기 위한 정보가 포함(Self-contained)되어 있다.
⌛ TL;DR
* Base64 URL-safe Encoding: Base64 Encode에서 URL 오류 방지를 위해 ‘+’, ‘/’를 ‘-’, ‘_’로 표현한 인코딩
** Header: 토큰과 해시 알고리즘 타입 정보
** Payload: 서버에서 전달할 Data
Sig=ECDSA(SHA256(B64(Header).B64(Payload)), PrivateKey)
Header, Payload → Base64 URL-safe Encoding → SHA256(Header에 명시된 해시 알고리즘) → 개인키를 통한 ECDSA 암호화
JWT=B64(Header).B64(Payload).B64(Sig)
**전자서명 자체도 Base64 URL-safe 인코딩한다.
장점
단점