글이 긴 것 같아 필요에 따라 볼 수 있게 앵커로 먼저 정리한다.
- 원격 레포지토리로부터 로컬로 서브모듈 가져오기(이동) (2022.08.20. 브랜치를 나누어 작업하는 경우 내용 추가)
- 로컬에서 수정한 서브모듈 원격 레포지토리로 올리기(이동)
- 프로젝트에 적용하기(이동)
- (2022.07.13.) 권한이 없는 사용자에 대해 민감정보가 보호되는 모습(이미지) (이동)
- (2022.08.14.) EC2 CLI 환경에서 submodule 가져오기 (GitHub access token 을 이용한 authentication) (이동)
1. 찾아보게 된 배경
약 6개월 정도 서버 공부를 하며 혼자 로컬에서 작업하는 경우가 많았기에, 민감 정보는 .gitignore 로 숨길 수 있어 굳이 정보를 숨기기 위한 다른 방법을 찾아보지 않았었다.
하지만 이번 프로젝트를 진행하며, 중요하거나 민감한 정보 또한 버전관리가 되면서 github에 보이지 않을 방법이 필요했다.
2. submodule 기능을 사용하기로 결정한 이유
기존에 쓰던 방법 .gitignore 만 사용하기. 항상 사용하던 방식이다.
단순히 민감한 정보를 git 이 관리하지 않도록 한 후, 다른 곳에서 작업할 일이 있다면 파일을 직접 주고 받았다. 하지만 이렇게 사용할 때에는 저 application.yml 의 내용이 달라질 때마다 당연히 파일을 주고 받아야하는 불편함이 있었다. 앞으로 개발자로서 더 큰 단위의 팀에서 일을 하기 위해서는 조금 더 자동화된 방법이 필요하다고 생각했다.
그렇게 구글링을 해보니
- git에 직접적으로 내용이 노출되지 않아야한다.
- 파일로 주고받을 필요 없이 git을 통해 형상관리가 되면 좋겠다.
private 레포지토리를 만들어 submodule 을 이용하는 방식은 위 두가지 조건을 모두 충족했다.
3. submodule 사용방법 및 적용
submodule 에 대해서는 아래 링크들을 참고하였다.
https://git-scm.com/book/ko/v2/Git-%EB%8F%84%EA%B5%AC-%EC%84%9C%EB%B8%8C%EB%AA%A8%EB%93%88
https://tecoble.techcourse.co.kr/post/2021-07-31-git-submodule/
https://www.youtube.com/watch?v=TAe4uZqYt6c&ab_channel=%EC%83%9D%ED%99%9C%EC%BD%94%EB%94%A9
https://jujeol-jujeol.github.io/2021/07/12/git-submodule-%EC%A0%81%EC%9A%A9%ED%95%98%EA%B8%B0/
1. 정보를 담을 private 레포지토리 생성
2. 서브모듈 등록
로컬에서 서브모듈을 사용하고 싶은 레포지토리 경로까지 이동 후, 해당 위치에서 아래와 같은 명령어를 입력해준다.
$ git submodule add {서브모듈로 사용할 레포지토리 url}
or
$ git submodule add -b {생성할 브랜치명} {서브모듈로 사용할 레포지토리 url}
입력 후 확인해보면, 위 이미지와 같이 .gitmodules 파일과 private repository에 저장해 둔 application.yml 파일이 생긴 것을 확인할 수 있다. 그 후 원격 레포지토리에 push 해준다면 submodule 등록은 완료되는 것이다.
다음으로 이렇게 적용한 서브모듈을 다른 팀원과 함께 사용하는 방법을 알아보자. 크게 원격 레포지토리로부터 로컬로 서브모듈 가져오기(이동), 로컬에서 수정한 서브모듈 원격 레포지토리로 올리기(이동) 이렇게 두 가지로 나누어 작성한다.
(2022.07.13.) 질문이 있어서 submodule 이 민감정보를 보호하는 모습도 글 마지막에 이미지로 덧붙였다. (이동)
3. 원격 레포지토리로부터 서브모듈 가져오기, 시나리오에 따른 분류
- 프로젝트를 처음 클론하는 경우
- 프로젝트를 진행 중 서브모듈이 생겼을 경우
- 서브모듈을 포함하여 프로젝트를 진행 중 서브모듈이 수정되었을 경우 (2022.08.20. 수정)
(2022.08.20.) 브랜치를 나누어 작업하는 중 서브모듈이 수정되었을 경우에 대해 내용 보충
3-1. 프로젝트를 처음 클론하는 경우 & 3-2. 프로젝트를 진행 중 서브모듈이 생겼을 경우
이 경우 단순히 git clone 을 통해 원격 레포지토리를 클론하게 되면, 혹은 원격 레포지토리를 pull 하게 되면,
해당 이미지와 같이 .gitmodules 와 서브모듈이 위치하는 폴더는 함께 들어오지만, private 레포지토리에 저장되어있는 '파일'은 함께 받아지지 않는다.
서브모듈이 꼬리의 꼬리를 물고 굉장히 많이 연결 되어있을 때, 그 중 일부만 사용해야 할 수도 있으므로 기본적으로 서브모듈은 사용할 파일을 사용자가 직접 명시하여 가져와야한다. 하지만, 서브모듈이 갖고 있는 정보가 그리 많지 않고, 한 번에 전부 불러와도 괜찮다면
$ git clone --recurse-submodules {원격 레포지토리 url}
위와 같은 명령어를 통해 원격 레포지토리를 클론할 때 연관된 모든 서브모듈 또한 함께 받아올 수 있다.
위 명령어를 풀어쓰자면 아래와 같다. 아래와 같은 명령어 형태를 통해서도 서브모듈을 불러올 수 있다.
# 해당 명령어의 경우 이미 원격 레포지토리를 clone 해 온 상태라고 가정합니다.
# .gitmodules 파일에 있는 정보를 .git/config에 등록한다.
$ git submodule init
# submodule 클론
$ git submodule update
이 때 'init' 과 'update' 에 대한 옵션이 몇 개 더 존재한다.
1. 특정 파일만 서브모듈로 등록하기
$ git submodule init {파일명}
init 뒤에 특정한 파일명을 입력해준다면, 해당 파일만을 submodule 로 등록하게 된다.
2. 모든 파일을 등록하며, 현재의 내 프로젝트 commit 이 참조하고있는 서브모듈에 대한 정보를 가져올 경우
$ git submodule init
$ git submodule update
해당 코드와 같이 init 후 단순히 update 만 적어준다면, 현재 작업 중인 commit 이 참조하고 있는 서브모듈을 내 로컬로 가져오게 된다.
3. 모든 파일을 가져오며, 현재 서브모듈 원격저장소 최신 상태의 commit 정보를 가져올 경우
$ git submodule init
$ git submodule update --remote
update 뒤에 --remote 를 붙여준다면, 현재 서브모듈 원격저장소에 저장되어있는 상태를 내 로컬로 가져오게 된다. 현재는 '서브모듈이 처음 등록된' 시나리오이므로, 2번과 3번의 차이가 없을 것이다. 하지만 서브모듈에 수정이 발생한다면 둘을 구분해서 바르게 써야한다. (즉, 지금은 둘의 차이를 몰라도 된다....)
아래 내용은 내가 서브모듈을 수정할 일이 없다면 읽지 않아도 된다.
'clone 과 동시에 받아오기', 'clone 후 서브모듈 받아오기' 두 가지에 대해 소개하였다. 이제 cd 명령어로 서브모듈이 포함된 디렉토리로 이동해보자, 서브모듈도 개별적인 레포지토리이므로 branch 를 확인해보면
위 이미지와 같이 서브모듈을 추적하는 브랜치가 없음을 확인할 수 있다. 변경 내역을 추적하는 브랜치 없이 서브모듈을 (위 이미지에서 TodayHouse-Secret 안의 파일을) 수정하게 되면, 당연히 git 은 내가 수정한 내용을 main 브랜치와 연관짓지 못할 것이다.
때문에 서브 모듈을 원격 레포지토리로부터 가져온 후, 내가 수정을 해야한다면 반드시 적절한 branch로 checkout 해주어 git 이 로컬의 서브모듈을 추적하도록 해야한다.
정리하자면
$ git clone --recurse-submodules {원격 레포지토리 url}
or
$ git clone {원격 레포지토리 url}
$ git submodule init
$ git submodule update or $ git submodule update --remote
# 서브모듈이 처음 등록된 상황에서는 두 명령어에 차이가 없다.
위 코드와 같이 서브모듈을 불러올 수 있다.
3-3. 서브모듈을 포함하여 프로젝트를 진행 중 서브모듈이 수정되었을 경우
이 경우에는 현재 내 branch 가 참조하고 있던 submodule 이 새로 올라온 commit hash 를 참조하도록 업데이트를 해주어야 한다. 말로 이해하기 어렵기 때문에, 예시로 보여주자면 다음과 같다.
첫 번째 이미지에서 'git submodule', 'git submodule update' 로 현재 내 브랜치가 f6c8286 이라는 서브모듈의 commit 을 참조하고 있었음을 알 수 있다. 이 때 서브모듈에 수정사항이 생겨서 새로운 commit 이 올라왔다면, git submodule update --remote 를 해주어 새로운 commit 인 55a1ce9 를 참조하도록 업데이트 해주어야 한다.
$ git submodule update --remote
다음과 같이 update --remote 만 진행해주면 끝이다.
※ 주의할 점 ※
서브모듈에 수정사항이 생겼는데, 이를 무시하고 그냥 내 작업을 push 하려 한다면 아래와 같은 상황을 마주하게 된다.
내가 작업중인 디렉토리에서 서브모듈의 의미는 서브모듈 원격 레포지토리에서 참조할 commit hash 를 가리키는 것 뿐이다. 실제로 그 서브모듈의 내용물을 갖고 있는 것이 절대 아니다.
때문에 내 브랜치가 merge 될 브랜치가 참조하고 있는 서브모듈의 commit hash 와, 내 브랜치가 참조하고 있는 서브모듈의 commit hash 가 다르다면, git 은 이것에 대해 '참조할 submodule 의 commit hash 가 다르네?' 라고 변경사항으로 생각해 위와 같이 보여줄 것이다.
4. 로컬에서 수정한 서브모듈 원격 레포지토리로 올리기
로컬에서 서브모듈을 수정할 일이 생긴다면 꼭
$ git submodule update --remote
위 명령어로 원격 레포지토리에서의 변경점은 없는지 로컬과 merge 를 먼저 진행 후 수정해주자.
그 후 서브모듈 수정을 완료하였다고 가정하면, 서브모듈 또한 하나의 레포지토리이므로 서브모듈 디렉토리로 이동하여 add, commit, push 의 과정을 통해 서브모듈 레포지토리로 push 해주면 된다.
하지만 반드시 명심해야할 점이 있다. 다시 말하지만, 서브모듈을 포함하고 있는 메인프로젝트는 서브모듈 그 자체를 갖고 있는 것이 아니라 서브모듈 원격 레포지토리의 commit 내역을 '참조' 하고 있는 것이므로, 서브모듈에 수정사항이 생겼다면 꼭 서브모듈 먼저 push 후 메인 프로젝트를 push 하여야 한다.
그렇지 않고 메인 프로젝트 먼저 push 해버린다면, 해당 메인 프로젝트를 pull 한 다른 사람은 내가 수정하기 이전의 서브모듈을 참조하게 된다.
이를 방지하게 위해 git 에서는 두 가지 종류의 명령어를 제공한다. 메인프로젝트를 push 하며 다음과 같이 명령어를 작성하면 된다.
$ git push --recurse-submodules=check
of
$ git push --recurse-submodules=on-demand
첫 번째 명령어는 서브모듈의 로컬 커밋이 remote 로 push 되지 않았다면, 메인프로젝트의 push 를 실패하도록 하는 옵션이다.
두 번째 명령어는 git 이 메인프로젝트를 push 하기 이전에 submodule 로 들어가서 push 를 해 준 후, 메인프로젝트를 push 해주는 옵션이다.
5. 메인 프로젝트에 적용하기
build.gradle 에 다음과 같이 코드를 작성해주면 된다.
- from : 해당 폴더 경로로부터
- include : *.yml 와일드카드 입력이므로 .yml 로 끝나는 모든 파일을 포함하여
- into : 해당 경로로 copy 한다.
위와 같은 의미를 가지도록 작성해주면 서버를 실행할 때 서브모듈의 파일들이 복사되어 src/main/resources 에 보이게 된다.
* 번외 1 - submodule 로 정말 민감정보를 보호할 수 있는가 *
(2022.07.13.) 질문이 들어와서 submodule 을 간단하게 테스트해보았다.
- 인터넷 자격증명, git user 계정 정보 바꾸기 (해당 계정은 가져오고자 하는 서브모듈 레포지토리에 대해 권한이 없음.)
- 바꾼 계정으로 submodule update 시도하기
- 다시 원래의 계정으로 바꾸기 (서브모듈 레포지토리에 권한이 있는 계정)
- 다시 submodule udpate 시도하기
위 이미지와 같이 권한이 없는 임의의 GitHub 계정으로 바꾸어주었다. git 계정 바꾸는 방법은 구글에 검색하면 쉽게 알 수 있다.
이 상태로 submodule 을 가져오려 한다면 submodule init 까지는 성공하지만, 가져오기 위한 update 는 실패하는 것을 볼 수 있다.
서브모듈 레포지토리에 권한이 있는 원래 계정으로 바꾼 후 다시 update 를 시도하면 다음과 같이 브라우저 로그인을 거친 후
성공적으로 submodule 을 가져오는 것을 확인할 수 있다.
* 번외 2 - EC2 등 CLI 환경에서 submodule 을 가져오기 위한 권한 부여받기 *
(2022.08.14.) 프로젝트를 EC2 에 올리기 위해 git clone 을 하고 submodule 을 가져오려 하던 중
password 를 이용한 authentication 은 안된다는 메시지를 받았다.
그래서 참고하라고 던져 준 링크로 들어가보니
access token 을 이용하라고 한다.
글에서 안내한대로 GitHub 에서 access token 을 발급받은 후
$ git config user.name "name"
$ git config user.email "email"
실제 GitHub 에서 사용하는 user name, email 로 계정 설정을 해주고, 'Password for' 부분에서 발급받은 access token 을 붙여넣기 해주면
성공적으로 submodule 을 가져올 수 있다.
'개발 관련 > Git' 카테고리의 다른 글
[Git] git 실수로 변경한 파일의 변경사항을 되돌리는 방법 (0) | 2022.08.20 |
---|---|
[Git] git 명령어 (0) | 2021.08.02 |
[Git] fork한 repository 동기화부터 pull request (PR)를 보내기까지 (0) | 2021.08.02 |
댓글