`git`에 대해서 한창 공부할 때도 있었는데,

요즘엔 쓰던 명령어만 쓰면서 그렇게 지내고 있던 와중에...

 

새로운 명령어(기능?)가 `high-level commands`로 추가되었다는 소식을 듣게 되었다.

 

`v2.23.0` 버전의 릴리스 노트에 `switch / restore` 2개의 새로운 명령어를 소개하고 있다.

  - https://github.com/git/git/blob/master/Documentation/RelNotes/2.23.0.txt

 

 

이하 과정은 `Ubuntu 18.04` 환경에서 진행했다.

 

 

1. 설치된 버전 확인

  - 새로운 명령어를 사용해보기 위해서는 `v2.23.0` 이상의 버전이 필요하다.

  - Ubuntu 환경에서 apt 패키지를 통해 설치되어있는 git 버전을 확인해보자.

$ git --version 
git version 2.17.1

 

  - 오래된 버전을 삭제하려면 다음과 같이...

$ sudo apt remove git

$ sudo apt autoremove

 

 

2. 신규 버전 설치 (PPA)

  - 가장 편리한 방법인 PPA 추가해서 apt를 통해서 관리하는 방법이다.

$ sudo add-apt-repository ppa:git-core/ppa

$ sudo apt update

$ sudo apt install git

 

 

3. 신규 버전 설치 (Source)

  - 개인적인 취향으로 좋아하는 방식인 Source Code 빌드해서 사용하기 ^^

    . https://git-scm.com/book/en/v2/Getting-Started-Installing-Git

$ sudo apt-get install dh-autoreconf libcurl4-gnutls-dev libexpat1-dev gettext libssl-dev asciidoc xmlto libz-dev docbook2x install-info

$ cd /srv/install/git

$ wget https://mirrors.edge.kernel.org/pub/software/scm/git/git-2.33.1.tar.gz

$ tar zxvf git-2.33.1.tar.gz

$ cd git-2.33.1

$ make configure

$ ./configure --prefix=/usr/local

$ make all doc info

$ sudo make install install-doc install-html

 

  - 자동 완성 기능도 설정하자

    . bash

$ sudo cp ./contrib/completion/git-completion.bash /etc/bash_completion.d/

  . zsh

$ mkdir -p ~/.zsh

$ cp ./contrib/completion/git-completion.bash ~/.zsh/
$ cp ./contrib/completion/git-completion.zsh ~/.zsh/_git

$ nano ~/.zshrc
...
zstyle ':completion:*:*:git:*' script ~/.zsh/git-completion.bash
fpath=(~/.zsh $fpath)

autoload -Uz compinit && compinit
$ source ~/.zshrc

 

  - git에서 결과 화면이 전환되는 방식으로 나오는 것이 싫은 경우

$ git config --global pager.branch false

 

 

4. New Command

  - 새로운 명령어 `switch / restore`는 기존 `checkout` 명령어의 일부 기능이 분리된 것이다.

    . `checkout` : Switch branches or restore working tree files

    . `switch` : Switch branches

    . `restore` : Restore working tree files

 

 

5. Before (As-was)

  - 기존에 해왔던 방식을 살펴보자

 

  - git source code를 가지고 알아보겠다. (사이즈가 좀 크지만 그래도 ^^)

$ cd /srv/workspace

$ git clone https://github.com/git/git.git

$ cd git/

  - branch 정보를 살펴보자

$ git branch -a
* master
  remotes/origin/HEAD -> origin/master
  remotes/origin/maint
  remotes/origin/master
  remotes/origin/next
  remotes/origin/seen
  remotes/origin/todo

 

  - local에 `develop` branch를 생성해보자 = local branch 생성 + 현재 작업 branch 변경

$ git checkout -b develop                            
새로 만든 'develop' 브랜치로 전환합니다

$ git branch -a          
* develop
  master
  remotes/origin/HEAD -> origin/master
  remotes/origin/maint
  remotes/origin/master
  remotes/origin/next
  remotes/origin/seen
  remotes/origin/todo

  - 다시 `master` branch로 변경해보자

$ git checkout master
'master' 브랜치로 전환합니다
브랜치가 'origin/master'에 맞게 업데이트된 상태입니다.

$ git branch -a      
  develop
* master
  remotes/origin/HEAD -> origin/master
  remotes/origin/maint
  remotes/origin/master
  remotes/origin/next
  remotes/origin/seen
  remotes/origin/todo

  - 파일 하나를 변경하고 staging까지 해보자

$ nano README.md

$ git status   
현재 브랜치 master
브랜치가 'origin/master'에 맞게 업데이트된 상태입니다.

커밋하도록 정하지 않은 변경 사항:
  (무엇을 커밋할지 바꾸려면 "git add <파일>..."을 사용하십시오)
  (use "git restore <file>..." to discard changes in working directory)
수정함:        README.md

커밋할 변경 사항을 추가하지 않았습니다 ("git add" 및/또는 "git commit -a"를
사용하십시오)

git add README.md

git status
현재 브랜치 master
브랜치가 'origin/master'에 맞게 업데이트된 상태입니다.

커밋할 변경 사항:
  (use "git restore --staged ..." to unstage)
수정함:        README.md

  - staged 상태에 있는 파일을 빼내자

$ git reset HEAD README.md
리셋 뒤에 스테이징하지 않은 변경 사항:
M README.md

$ git status
현재 브랜치 master
브랜치가 'origin/master'에 맞게 업데이트된 상태입니다.

커밋하도록 정하지 않은 변경 사항:
  (무엇을 커밋할지 바꾸려면 "git add <파일>..."을 사용하십시오)
  (use "git restore <file>..." to discard changes in working directory)
수정함:        README.md

커밋할 변경 사항을 추가하지 않았습니다 ("git add" 및/또는 "git commit -a"를
사용하십시오)

  - 변경된 파일을 원복 해보자

$ git checkout -- README.md 

$ git status               
현재 브랜치 master
브랜치가 'origin/master'에 맞게 업데이트된 상태입니다.

커밋할 사항 없음, 작업 폴더 깨끗함

 

 

 

6. Now (To-be/is)

  - 이제 새로운 명령어로 위의 과정을 다시 해보자

 

  - `develop-2` branch를 생성하고 이동해보자

$ git switch -c develop-2
새로 만든 'develop-2' 브랜치로 전환합니다

$ git branch -a
  develop
* develop-2
  master
  remotes/origin/HEAD -> origin/master
  remotes/origin/maint
  remotes/origin/master
  remotes/origin/next
  remotes/origin/seen
  remotes/origin/todo

  - `master` branch로 이동!

$ git switch master
'master' 브랜치로 전환합니다
브랜치가 'origin/master'에 맞게 업데이트된 상태입니다.

$ git branch -a
  develop
  develop-2
* master
  remotes/origin/HEAD -> origin/master
  remotes/origin/maint
  remotes/origin/master
  remotes/origin/next
  remotes/origin/seen
  remotes/origin/todo

  - 파일 하나 수정

$ nano README.md

$ git status
현재 브랜치 master
브랜치가 'origin/master'에 맞게 업데이트된 상태입니다.

커밋하도록 정하지 않은 변경 사항:
  (무엇을 커밋할지 바꾸려면 "git add <파일>..."을 사용하십시오)
  (use "git restore <file>..." to discard changes in working directory)
수정함:        README.md

커밋할 변경 사항을 추가하지 않았습니다 ("git add" 및/또는 "git commit -a"를
사용하십시오)

git add README.md

git status
현재 브랜치 master
브랜치가 'origin/master'에 맞게 업데이트된 상태입니다.

커밋할 변경 사항:
  (use "git restore --staged ..." to unstage)
수정함:        README.md

  - 파일을 일단 unstaged 상태로~

$ git restore --staged README.md

$ git status
현재 브랜치 master
브랜치가 'origin/master'에 맞게 업데이트된 상태입니다.

커밋하도록 정하지 않은 변경 사항:
  (무엇을 커밋할지 바꾸려면 "git add <파일>..."을 사용하십시오)
  (use "git restore <file>..." to discard changes in working directory)
수정함:        README.md

커밋할 변경 사항을 추가하지 않았습니다 ("git add" 및/또는 "git commit -a"를
사용하십시오)

  - 파일 원복!

$ git restore README.md

$ git status
현재 브랜치 master
브랜치가 'origin/master'에 맞게 업데이트된 상태입니다.

커밋할 사항 없음, 작업 폴더 깨끗함

 

 

지금까지 git에 새롭게 추가된 2개의 명령어 `switch / restore` 에 대해서 살펴보았다.

 

보면 알겠지만 기존에 안되던 새로운 기능이 추가된 것은 아니고

`checkout`에서 했던 기능 中 일부분을 분리해서 구성한 것일뿐이다.

 

기존에 `checkout`을 잘 사용해왔던 분들이라면, "굳이 왜~?"라는 말을 할 수도 있겠으나

처음 git을 접하는 분들이라면 조금 더 직관적인 명령어로 느끼지 않을까라는 생각이 든다.

 

그 동안 너무 git을 멀리해왔던 것 같아서 간만에 포스팅해봤다!

 

 

반응형

'SCM > Git-GitHub' 카테고리의 다른 글

Universe 2021 & GitHub Actions  (0) 2022.01.18
github.dev (Web-IDE)  (1) 2021.11.03
git 설치 (Git 2.33.0, Windows 10)  (0) 2021.10.02
GitHub Copilot 처음 써보기  (0) 2021.07.26
GitHub CLI (GitHub Command line)  (0) 2020.09.20

 

정말 간만에 해보는 git 설치.

거기에다가 windows 10 환경은 정말 정말 오랜만이다.

 

 

1. Homepage

   - 모든 시작은 홈페이지

   - https://git-scm.com/

 

2. Download & Install

   - 홈페이지에서 친절하게 알맞은 아이를 추천해준다.

   - 오른쪽 모니터 화면에 있는 `Download for Windows`를 클릭해서 다운로드 후 설치 진행하자.

   - 잘 모르겠으면 추천하는대로 `Next`를 선택하면 된다 ^^

   - 개인적인 취향으로 기본 에디터를 선택하면 되는데, 저는 `nano`를 좋아하므로... ^^

 

3. Test

   - 잘 설치되었는지 확인해보자.

   - 윈도우즈의 `cmd`를 이용해서 해도 되지만, 이왕이면 `Git Bash`로 한 번 해보자.

   - 시작 메뉴에서 `Git Bash`를 클릭하자.

   - 그리고 실행

$ git --version

 

끝~

반응형

'SCM > Git-GitHub' 카테고리의 다른 글

github.dev (Web-IDE)  (1) 2021.11.03
git switch/restore (git 새로운 명령어)  (1) 2021.10.17
GitHub Copilot 처음 써보기  (0) 2021.07.26
GitHub CLI (GitHub Command line)  (0) 2020.09.20
git clone [bare/mirror] 에 대해서 알아보기  (0) 2020.01.01

 

주석만 작성해도, function 이름만 적어줘도 AI가 코드를 대신 작성해준다고 하는 Copilot !!!

 

광고/홍보를 그렇게 해놓고는...

한정된 사람들만 사용할 수 있게 해주는 불친절한 GitHub !! 아니 MS !!!

 

 

뭐 어떻게 어떻게 사용해볼 수 있기 기회를 얻어서

다음과 같이 사용해보았다.

 

Already enabled

 

내 본캐 계정에서는 아직도 대기중인데...

 

Extension

 

GitHub 웹사이트에서 바로 사용하는 것은 말이 안되기에 어떤 방식으로 제공해주나 했는데...

Visual Studio Code Extension 형태로 제공해준다 !!!

Extension 설치 !!!

 

VSCode Extension

 

21만명이 사용하고 있나보다.

별점이 4개 밖에 안되네!? ㅋㅋㅋ

 

Sign in to GitHub

 

당연하게도 GitHub 로그인 과정을 거쳐야 한다!!!

 

Authorize

 

token

 

열기 하니까 잘 되었다.

잘 안되는 사람들은 아래에 나오는 방식으로 진행하면 되겠죠 ?!

 

function

 

사용법은 간단하다.

함수 이름 작성 하고 파라미터 정의하고 `{` 입력하면 회색으로 갑자기 딱! Suggestion을 보여준다.

 

마음에 들면 `Tab`키 누르면 되고,

마음에 안들면 `Alt + [` 또는 `Alt + ]` 누르면 다른 suggestion 들을 보여주게 된다.

 

그런데, 속도 이슈인지 `Alt + [` 또는 `Alt + ]` 눌렀을 때에 전환이 잘 안되는 경우가 많았다.

 

Ctrl + Enter

 

Suggestion 목록을 한 번에 보고 싶으면 `Ctrl + Enter`를 누르면 된다.

위 그림과 같이 오른쪽에 suggestion 목록을 전체 보여준다.

 

속도 이슈로 한번에 나오지 않더라도 기다리면 주르륵 나온다.

`Alt + [` 또는 `Alt + ]`는 다른 suggestion이 없는 것인지 아직 로딩 중인지 알 수 없어서 불편한데

차라리 그냥 `Ctrl + Enter`를 이용해서 전체를 보고 하는 것이 좋을 것 같다.

 

주석

 

함수 이름만으로는 의도를 제대로 전달하기 어려울 수 있다.

그럴 때에는 주석을 앞에 적어주면 된다.

 

Framework

 

함수만 지원하는 것도 아니다.

Express server를 사용하겠다라는 주석만으로도 코드를 제안해준다.

 

 

 

지금까지 알아본 과정은 GitHub에서 제공해주는 Start Guide로 진행해보았다.

- https://github.com/github/copilot-preview/blob/main/docs/gettingstarted.md

 

혹시 웹 관련된 JS만 잘되는 것 아닐까?

 

Python

 

확장자가 `*.py`인 파일을 만들고

`Authentication to GitHub Enterprise instance`와 같이 주석을 작성해보았다.

 

와우! stackoverflow 검색 보다는 훨씬 빠르게 코드를 찾아준다.

다만, 내용을 살펴보니 내가 원하는 실제 사용가능한 수준으로까지는 없었다.

 

주석 내용을 조금 더 디테일하게... 구체적으로 적어줘야 원하는 내용을 제안해줄 것으로 보인다.

 

한글

 

한글도 지원을 잘 해줄까!?

 

위 그림과 같이 잘 해준다 !!!

 

한글로 된 주석이 github.com에 그다지 많지 않을거라

제한적인 상황에서만 유용할 것 같지만,

여하튼 한글도 된다 !!!

 

token

 

업로드 한 사람의 잘못이긴 하겠지만

위 그림과 같이 secret 값들도 그대로 suggestion 된다.

 

이런 부분은 주의해야할 것 같다.

 

 

결론적으로 원하는 사항에 대해서 잘 정의할 수 있으면

최소한 Stackoverflow 검색하는 것보다 빠른 시간 안에 code를 suggestion 받을 수 있는 재미있는 기능이다.

 

실무에서도 유용할 지에 대해서는 직접 프로젝트를 진행하면서 사용해봐야 할 것이고,

최소한 PoC 하거나 처음 해보는 사항에 대해서 접근할 때에는 상당히 유용할 것으로 보인다.

 

반응형


형상관리 도구로써

Git 자체는

Command line 방식으로

사용하는 것을 추천한다.


나만 이렇게 생각하는 것은 아니라고 생각한다.

많은 분들이 동감할 것이다.



그래서

Windows 환경에서도

Git-bash를 사용해서

Git을 사용하고 있는데...






문제는

GitHub를 사용할 때에는

결국

Web 환경을 사용할 수 밖에 없다.



Issue를 확인한다던지,

Pull-Request를 한다던지...




하지만, 웹을 사용하기 어려운 경우...

아니면, 웹을 사용하기 싫은 경우...


우리에게 필요한 것은 뭐 ?!


"GitHub CLI"



최근에 GitHub에서 version 1.0을 릴리즈 하였다.



https://cli.github.com/





1. Installation (Win)



설치는 그냥 다운로드 받아서 Next 연타 하면 끝

(Linux, Mac도 손쉽게 할 수 있다)



실행은

Git-bash 또는 PowerShell

모두 잘 된다.







2. Authentication


Beta 버전 때에는 Enterprise를 지원하지 않는데,

v1.0 정식 릴리즈에서는

github.com + Enterprise

모두 잘 지원한다 !!!


예를 들어서 Issues 목록을 보고 싶다고 하는 경우

GitHub Client에게

어떤 repository의 Issues 목록을 보고 싶은지를

알려줘야 한다.


그리고 또하나 필요한 것은

Issues를 읽어올 수 있는

인증/권한을 셋팅하는 것 !!!



기본적인 인증 등록은 아래와 같다.


GitHub-bash에서는 정상동작하지 않는다.

PowerShell에서 실행하면 된다.


$ gh auth login


GitHub.com과 Enterprise를 고를 수 있다.



일단, GitHub.com을 선택해보았다.



웹브라우져로 할 수도 있고,

token값을 넣을 수도 있다.


웹브라우져를 선택했다.



코드값 잘 복사해놓고 엔터를 누르면 된다.



default 브라우저가 IE로 되어있으면

잘 안될 수도 있다고 한다.


Chrome 권장


위에서 복사한 코드값 넣고 'Continue' 클릭~



권한 주면 된다.


패스워드 한 번 더 확인해주고~



축하받으니 뭔가 좋긴 한데... ^^



앞에 화면 하나 캡처하지 못했는데...


기본 프로토콜로 HTTPS 사용할건지 SSH 사용할건지 묻는 화면도 있다.


굳이 HTTPS 사용할 이유는 없어서 SSH로 설정했다.






3. Usage


이제 어떻게 동작하는지 살펴보자.


> gh issue list -R [OWNER/REPO]



텍스트로 목록을 잘 보여준다.

한글도 잘 나오는 것을 볼 수 있다.



> gh issue view [이슈번호] -R [OWNER/REPO]



텍스트로 본문도 볼 수 있다.


"--web" 옵션을 사용하면 브라우져로 확인할 수도 있다.






사용할 수 있는 명령어들과 옵션들은 아래 사이트에서 확인할 수 있다.


https://cli.github.com/manual/




반응형


옛날 옛날 한 옛날에.... 잠시 궁금했던 git clone 옵션들... [ bare / mirror ]


한 번 테스트 해본다고 마음 먹은지 몇 년만에 갑자기 하고 싶다는 의욕이 불끈! ... 은 거짓말이고

회사 업무 中 [ bare / mirror ]  옵션의 차이에 대한 문의가 있었고

이에 대해서 한 번 살펴보고 싶어졌다!!!


0. clone

    - 일단 무조건 clone 해봤다.

$ git clone git@github.com:tensorflow/tensorflow.git ./tensorflow-normal

Cloning into './tensorflow-normal'...

remote: Enumerating objects: 3, done.

remote: Counting objects: 100% (3/3), done.

remote: Compressing objects: 100% (3/3), done.

remote: Total 796000 (delta 0), reused 3 (delta 0), pack-reused 795997

Receiving objects: 100% (796000/796000), 453.08 MiB | 8.29 MiB/s, done.

Resolving deltas: 100% (643770/643770), done.

Checking out files: 100% (19052/19052), done.


$ du -hs ./tensorflow-normal
690M    ./tensorflow-normal


$ git clone --no-checkout git@github.com:tensorflow/tensorflow.git ./tensorflow-no

Cloning into './tensorflow-no'...

remote: Enumerating objects: 3, done.

remote: Counting objects: 100% (3/3), done.

remote: Compressing objects: 100% (3/3), done.

remote: Total 796000 (delta 0), reused 3 (delta 0), pack-reused 795997

Receiving objects: 100% (796000/796000), 453.51 MiB | 8.85 MiB/s, done.

Resolving deltas: 100% (643732/643732), done.


$ du -hs ./tensorflow-no
475M    ./tensorflow-no


$ git clone --bare git@github.com:tensorflow/tensorflow.git ./tensorflow-bare

Cloning into bare repository './tensorflow-bare'...

remote: Enumerating objects: 3, done.

remote: Counting objects: 100% (3/3), done.

remote: Compressing objects: 100% (3/3), done.

remote: Total 796000 (delta 0), reused 3 (delta 0), pack-reused 795997

Receiving objects: 100% (796000/796000), 455.34 MiB | 8.28 MiB/s, done.

Resolving deltas: 100% (643815/643815), done.


$ du -hs ./tensorflow-bare
477M    ./tensorflow-bare


$ git clone --mirror git@github.com:tensorflow/tensorflow.git ./tensorflow-mirror

Cloning into bare repository './tensorflow-mirror'...

remote: Enumerating objects: 1124, done.

remote: Counting objects: 100% (1124/1124), done.

remote: Compressing objects: 100% (1116/1116), done.

remote: Total 1055983 (delta 805), reused 21 (delta 8), pack-reused 1054859

Receiving objects: 100% (1055983/1055983), 1.09 GiB | 8.69 MiB/s, done.

Resolving deltas: 100% (783532/783532), done.


$ du -hs ./tensorflow-mirror
1.2G    ./tensorflow-mirror



1. 정리

    - 위 내용을 표로 정리하면 아래와 같다.


구분 

 normal

 --no-checkout

--bare 

--mirror 

objects 

796,000 

796,000 

796,000 

1,055,983 

Receiving Size 

453.08 MiB 

453.51 MiB 

455.34 MiB 

1.09 GiB 

du Size 

690 M 

475 M 

477 M 

1.2 G 



2. 도식화

    - 위의 상황을 그림으로 설명해보면 아래와 같다.




3. 설명

    - normal

        . 당연히 commit 이력을 모두 담고 있고, 거기에다가 기본 branch로 설정된 소스코드가 working tree에 존재하게 된다.

    - no-checkout

        . commit 이력을 모두 담고 있고, 아직은 working tree에 소스코드를 넣어놓지는 않은 상태다.

    - bare

        . commit 이력만 담고 있다

    - mirror

        . 일반적인 commit 이력뿐만 아니라, 숨어있는(?) 모든 이력들을 담고 있다.


    # 적고나니 이게 뭔 설명인가 싶네.... ^^



4. 차이점 살펴보기

    - normal vs no-checkout

        . HEAD가 가리키는 기본 branch의 latest commit으로 checkout 했냐/안했냐의 차이만 있다.

        . no-checkout으로 clone 한 뒤에 "git checkout -b master"를 하면 결국 똑같다.


    - normal vs bare

        . bare 옵션으로 clone을 하는 것은 개발을 하고자 하는 용도가 아니다. 그러므로 working tree는 없다.

        . normal clone을 했을 때 ".git" 디렉토리 부분만 있는 것이 bare 옵션이기 때문이다.

$ diff ./tensorflow-bare/config ./tensorflow-normal/.git/config

4c4,5

<       bare = true

---

>       bare = false

>       logallrefupdates = true

6a8,11

>       fetch = +refs/heads/*:refs/remotes/origin/*

> [branch "master"]

>       remote = origin

>       merge = refs/heads/master

        . 위의 차이를 보면 알겠지만, bare 옵션으로 clone을 하게 되면 remote를 바라보지 않는다


    - bare vs mirror

        . mirror 옵션은 현재 서버에 기록된(?) 모든 사항을 전부 가져오게 된다.

$ nano ./tensorflow-mirror/packed-refs

# pack-refs with: peeled fully-peeled sorted

4be56f381cd000e91f79209aaf150636db6fb840 refs/heads/0.6.0

...

45e1e4598d3ebab316bf87df9160656f524af36c refs/heads/master

e1c85596366f3133c797f153dac34e01589a231f refs/pull/10000/head

c2d4f5e964503d17107123e51139aa8bbf27c57c refs/pull/10007/head

29d57e0360306de6bc9021eec4b633e96f3549f5 refs/pull/10008/head

ad9e6a95e53a4407db44e0436fc5318522e832cf refs/pull/10011/head

...

        . bare 옵션의 경우에는 "refs/heads/*" 항목만 보이지만,

        . mirror 옵션의 경우에는 "refs/pull/*" 항목도 보인다.

        . GitHub에서 Pull-Request를 할 때 사용되는 commit들이 기록되는 위치가 바로 "refs/pull/*" 이다.



위의 내용에 대해서 잘 생각해보고 용도에 맞춰서 잘 사용하기 바란다~


반응형


Git 저장소를 오래 운영하다보니

호스팅하고 있는 서버의 스토리지가 부족한 일이 종종 발생한다. (Gerrit 또는 GitHub Enterprise)


(대체 왜 자꾸 바이너리를 올리는 것인지... 우이쒸~!!)



스토리지를 팍팍 늘리면 좋겠지만... 우리는 가난하기에.. ^^



이럴 때 보통 "git gc"를 실행하곤 하는데...

이게 성능/효과가 얼마나 있는지 실험을 해보고 싶었다!!!



0. target


    - 실험할 repo가 필요해서 찾던 中 최근 유명한 tensorflow를 대상으로 정했다.


$ git clone --bare https://github.com/tensorflow/tensorflow.git


    - 저장공간을 줄이는 것에 대한 실험이니만큼 "--bare" 옵션으로 clone 하였다.


$ du -hs ./

455M    ./


    - 기본 저장 공간은 "455M"




1. [ git gc --aggressive ]


    - 가장 기본적으로 사용하는 옵션으로 해봤다. (오래걸렸다)


$ time git gc --aggressive

Counting objects: 769698, done.

Compressing objects: 100% (760700/760700), done.

Writing objects: 100% (769698/769698), done.

Total 769698 (delta 636704), reused 111483 (delta 0)

Checking connectivity: 769698, done.


real    41m45.048s

user    28m54.865s

sys     0m3.769s


$ du -hs ./

243M    ./







2. [ git gc --aggressive --prune=now ]


    - 구글링을 했더니, 안전하게 그리고 확실하게 gc를 하는 방법이라고 되어있는 2단계 실행법이다.

        . reflog는 "git rebase" 같은 작업을 하다가 발생하는 끈 떨어진(?) log들에 대한 정보이다.


$ git reflog expire --expire=now --all


$ time git gc --aggressive --prune=now

Counting objects: 769698, done.

Compressing objects: 100% (760700/760700), done.

Writing objects: 100% (769698/769698), done.

Total 769698 (delta 636704), reused 111483 (delta 0)

Checking connectivity: 769698, done.


real    41m17.315s

user    28m51.873s

sys     0m3.522s


$ du -hs ./

243M    ./






뭐 결론은 2번 방법으로 실행하면 되겠다~!!!

안전한게 짱이지~!!


조금은 실망~


반응형



최근 회사에서 Credential 내역이 노출되어 보안 위협이 된 사례가 발생을 하였다.


즉, 아이디/패스워드, AWS 토큰 값들을 소스파일 안에 적어놓고

그것을 그대로 commit 하여 push 까지 해버린 것이다.



그래서, 소스코드에 이러한 Credential 정보가 들어있는지 점검하는 것을 강화하였다.

자동으로 분석하도록 한 것이다.



문제는 이러한 Credential 정보가 들어있는 파일을 발견했을 때

개발자들이 어떻게 조치를 취해야하는지에 대한 가이드가 부재하고 있다는...





1. 기본 배경


    - 개발자들이 특정 API 사용을 위한 인증 정보를 파일에 적어놓고 무심코 commit을 했을 경우를 전제 해보자

    - 즉, 아래 그림과 같이 "commit D"에 token 값이 있다는 것을 발견한 것이다!!!



2. 최악의 해결 방법


    - Credential 정보가 발견되었다는 경고를 받은 개발자는 당황한 나머지 아래와 같이 작업을 할 수 있다.


    - 설마! 라고 하지만 정말로 저렇게 할 수 있다 !!!

    - 위와 같이 하면 "commit E"에서는 Credential 정보가 안보이지만, "commit D"로 checkout을 하면 볼 수 있게 되기에 해결책이 아니다 !!!!!




3. 기본적인 해결 방법


    - 실습을 위해 아래와 같이 실제 commit들을 만들어보았다.



    - 마지막 commit인 "2651682"에서 Credential 정보가 발견되었을 경우에 대한 대처법을 알아보자.


$ git clone git@github.com:whatwant/whatwant.git

Cloning into 'whatwant'...

remote: Enumerating objects: 8, done.

remote: Counting objects: 100% (8/8), done.

remote: Compressing objects: 100% (4/4), done.

Receiving objects: 100% (11/11), done.

Resolving deltas: 100% (2/2), done.

remote: Total 11 (delta 2), reused 8 (delta 2), pack-reused 3



$ cd whatwant/



$ git log --oneline

2651682 (HEAD -> master, origin/master, origin/HEAD) write token in no002.txt

a2004f0 add no002.txt

93afc28 add no001.txt

2b73c6e Initial commit



$ git reset --hard HEAD^

HEAD is now at a2004f0 add no002.txt



$ git log --oneline

a2004f0 (HEAD -> master) add no002.txt

93afc28 add no001.txt

2b73c6e Initial commit



$ git push origin master

To github.com:whatwant/whatwant.git

 ! [rejected]        master -> master (non-fast-forward)

error: failed to push some refs to 'git@github.com:whatwant/whatwant.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 push -f origin master

Total 0 (delta 0), reused 0 (delta 0)

To github.com:whatwant/whatwant.git

 + 2651682...a2004f0 master -> master (forced update)


    - 위와 같이 진행하고 commit 현황을 보면 "2651682" commit이 사라진 것을 볼 수 있다.



    - 아래 그림과 같이 표현할 수 있을 것이다



    - "git reset"은 매우 위험한 명령이기에 그냥 push를 하고자 하면 reject을 당한다! 그래서 "-f" 옵션을 통해 force 실행해야 한다!!!



4. 특정 파일의 이력을 모두 삭제하는 방법


    - 이번 포스팅을 하게 된 이유이다 !!!



    - 위와 같이 commit들이 있다고 해보자. 그림으로 표현하면 아래와 같다.



    - 즉, 예전에 이미 Credential 정보를 넣었는데... 불행하게도 뒤늦게 (이미 commit들이 쌓이고 난 뒤에) Credential 정보를 발견하게 된것이다.

    - 문제가 된 파일과 관련된 모든 이력을 지워보자.


$ git clone git@github.com:whatwant/whatwant.git

Cloning into 'whatwant'...

remote: Enumerating objects: 9, done.

remote: Counting objects: 100% (9/9), done.

remote: Compressing objects: 100% (7/7), done.

Receiving objects: 100% (13/13), done.

Resolving deltas: 100% (3/3), done.

remote: Total 13 (delta 3), reused 7 (delta 1), pack-reused 4



$ cd whatwant/



$ git log --oneline

d81bb67 (HEAD -> master, origin/master, origin/HEAD) add no003.txt

df3c9e0 write token in no002.txt

ea11c2d add no002.txt

83bc6a8 add no001.txt

2b73c6e Initial commit


$ git filter-branch --tree-filter "rm -f no002.txt" HEAD

Rewrite d81bb67affec459cd3e25fa57b98cf64a1bf05be (3/5) (1 seconds passed, remaining 0 predicted)

Ref 'refs/heads/master' was rewritten



$ ls -al

total 9

drwxr-xr-x 1 chani 197121  0 11월  9 20:41 ./

drwxr-xr-x 1 chani 197121  0 11월  9 20:40 ../

drwxr-xr-x 1 chani 197121  0 11월  9 20:41 .git/

-rw-r--r-- 1 chani 197121  0 11월  9 20:40 no001.txt

-rw-r--r-- 1 chani 197121  0 11월  9 20:40 no003.txt

-rw-r--r-- 1 chani 197121 10 11월  9 20:40 README.md



$ git log --oneline

69c84e3 (HEAD -> master) add no003.txt

94413d9 write token in no002.txt

1a2d568 add no002.txt

83bc6a8 add no001.txt

2b73c6e Initial commit



$ git push origin master

To github.com:whatwant/whatwant.git

 ! [rejected]        master -> master (non-fast-forward)

error: failed to push some refs to 'git@github.com:whatwant/whatwant.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 push -f origin master

Counting objects: 4, done.

Delta compression using up to 4 threads.

Compressing objects: 100% (4/4), done.

Writing objects: 100% (4/4), 515 bytes | 515.00 KiB/s, done.

Total 4 (delta 1), reused 0 (delta 0)

remote: Resolving deltas: 100% (1/1), done.

To github.com:whatwant/whatwant.git

 + d81bb67...69c84e3 master -> master (forced update)


    - 실제 commit이 어떻게 되어있는지 확인해 보자.



    - 무엇이 바뀌었는지 그림으로 확인해 보자.



    - 위의 방법은 문제가 발생한 파일과 관련한 내용을 전체 히스토리에서 삭제를 하는 것이다.

      → 그렇기 때문에, 영향을 받은 commit을 보면 앞의 commit 까지 포함이 된다.





※ 주의사항


    - 문제가 발생한 정확한 위치를 찾기가 어렵기 때문에 문제가 발생한 파일을 전체 history에서 삭제를 해버리는 방식이다.

      → 해당 파일에 Credential 정보 외의 내역도 있고 이에 대한 내용도 중요하다고 하면 문제가 있을 수 있는 방법이라는 말이다.


    - 그리고, 기존 commit ID 값도 변경이 된다.

      → commit ID 이력을 관리하고 있는 상황인 경우 문제가 있을 수 있다는 말이다.




이러한 번거로움을 피하기 위해서는 애초에 Credential 정보를 파일안에 기재하는 일이 없어야 하겠다.



반응형


업무 관련하여 GitHub의 로그인(인증)을 가지고 웹사이트를 구축하고자 알아보고 있다.

별도의 웹페이지를 구성하는데, 로그인 부분을 GitHub 것을 가지고 오고 싶은 것이다.


구글신님께 여쭤보니 자꾸만 Node.JS 기반의 샘플 코드만 알려주시는데,

미천한 중생인 필자는 구석기 시대를 살고 있는 무식한 종자이기에... 버겨웠다 ㅠㅠ


하지만, 구현은 해야하는데...


필자에게 남은 선택지는 두 가지 !!!

① Node.JS 공부하기

② 무조건 다른 방식 찾아내기


그러다가 우연히 만난 구글신님의 중얼거림..... "PHP로 구현한 샘플도 있는데..."


그래서, 대세 흐름은 아니지만 PHP로 구현한 코드를 직접 한 번 되는지 해보기로 했다.



1. WAS 환경 구축하기

    - Docker 기반으로 nginx + php 환경을 간단히 구축해봤다.

        ① Docker 설치하기 (링크)

        ② Docker-Compose 설치하기 (링크)

        ③ docker-compose.yml 작성


version: '3'


services:


    web:

        image: nginx:latest

        ports:

            - "80:80"

        volumes:

            - ./html:/code

            - ./web/conf/default.conf:/etc/nginx/conf.d/default.conf

            - ./web/log:/var/log/nginx


    php:

        image: php:7.3-fpm

        expose:

            - "9000"

        volumes:

            - ./html:/code


        ④ ./web/conf/default.conf 작성


server {

    listen 80;


    server_name 192.168.100.xxx localhost;


    index index.php index.html;


    root /code;


    location ~ \.php$ {

        try_files $uri =404;

        fastcgi_split_path_info ^(.+\.php)(/.+)$;

        fastcgi_pass php:9000;

        fastcgi_index index.php;

        include fastcgi_params;

        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;

        fastcgi_param PATH_INFO $fastcgi_path_info;

    }


    error_log  /var/log/nginx/error.log;

    access_log /var/log/nginx/access.log;

}


    ⑤ ./html/index.php


<?php


echo phpinfo();


?>


    ⑥ 브라우져로 접속해서 확인 → 성공~



※ 진행하다보니.... 집에서 VirtualBox로 생성한 서버에서 테스트를 진행하려다보니 여러가지 제약사항이 생겼다.

   일단 외부에 있는 GitHub.com에서 내부로 들어올 수도 없고..... 포트포워딩 등을 셋팅하면 되겠지만...

   야밤에 귀찮기도 하고... 그래서 외국에 있는 저렴이 서버 호스팅을 이용해서 테스트 진행하기로 했다.




2. GitHub 에서 App 등록하기


    - GitHub 인증을 이용하기 위해서는 GitHub에 "OAuth Apps"로 등록하는 과정이 필요하다.

    - 회사에서는 GitHub Enterprise에서 진행을 해야하지만, 지금 집에서는 GitHub.com을 이용하기로 했다.



    - GitHub.com 로그인 후 계정에서 Settings 메뉴 선택 후 Developer settings 항목을 선택하자



    - 우리가 사용할 것은 OAuth Apps 메뉴이다.



    - 위와 같이 정보를 채우자. (GitHub로 시작하는 이름은 사용할 수 없단다 ^^)

    - 생성할 때 callback URL을 어떻게 해야할지 몰라서 위와 같이 했는데... 실제 구성 時 로그인 페이지의 URL로 작성해주자.




    - 이제 우리에게 필요한 정보를 얻었다!!!




3. 페이지 구성하기


    ① index.php : 첫 접근 페이지

        - 이미 로그인이 되어있으면 main.php 페이지로 전환

        - 로그인을 원하면 login.php 링크 제공

<?php

session_start();


if (isset($_SESSION['github_data'])) {

    header("location: main.php");

}

?>

<a href="login.php">Login with Github</a>


    ② login.php

        - 로그인이 안되어 있으면 GitHub.com으로 보내버리고,

        - 로그인이 되어 있으면 세션에 사용자 정보를 넣고선 main.php로 전환

        - 위에서 생성한 정보는 각자 알맞게 입력!

<?php


$config = array(

    'client_id'     => 'xxx',

    'client_secret' => 'xxx',

    'redirect_url'  => 'http://xxx.xxx.xxx.xxx:8080/login.php',

    'app_name'      => 'WHATWANT GH Login'

);


session_start();


if($_SERVER['REQUEST_METHOD'] == 'GET') {

    if(isset($_GET['code'])) {


        $curl = curl_init('https://github.com/login/oauth/access_token');


        //TO DO: code 값이 없을 경우 처리

        $config['code'] = $_GET['code'];


        curl_setopt($curl, CURLOPT_RETURNTRANSFER, TRUE);

        curl_setopt($curl, CURLOPT_POSTFIELDS, http_build_query($config));

        curl_setopt($curl, CURLOPT_HTTPHEADER, array("Accept: application/json"));


        $json_response = curl_exec($curl);

        curl_close($curl);



        $token = json_decode($json_response);


        //TO DO: access_token 값이 리턴되지 않을 경우 처리

        $_SESSION['access_token'] = $token->access_token;


        $curl = curl_init("https://api.github.com/user?access_token=".$_SESSION["access_token"]);


        curl_setopt($curl, CURLOPT_HEADER, false);

        curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);

        curl_setopt($curl, CURLOPT_HTTPHEADER, array("Accept: application/json", "User-Agent: WHATWANT App"));


        $json_response = curl_exec($curl);

        curl_close($curl);


        $userdata = json_decode($json_response, true);



        $_SESSION['github_data'] = $userdata;

        header("location: main.php");

    }


    else {


        $url = "https://github.com/login/oauth/authorize?client_id=".$config['client_id']."&redirect_uri=".$config['redirect_url']."&scope=user";

        header("Location: $url");

    }

}


?>


    ③ main.php

        - 세션에 값이 없으면 index.php로 전환

        - 세션에 값이 있으면 정보 출력, 더불어 로그아웃 링크 제공

<?php

session_start();


if (!isset($_SESSION['github_data'])) {

    header("location: index.php");

}

else {


    foreach( $_SESSION['github_data'] as $key => $value ) {

        echo "$key => $value<br>";

    }


    echo "<a href='logout.php'>Logout</a>";

}

?>


    ④ logout.php

        - 세션값 날리고, index.php 페이지로 전환

<?php

session_start();

unset($_SESSION['github_data']);

header("Location: index.php");

?>


일단 급한대로 여기에서 마무리.

아직 구현하지 않은 부분은 구현하는대로 업데이트 하겠음~!!


참고사이트 : https://www.9lessons.info/2014/02/login-with-github-oauth-php.html


반응형

+ Recent posts