반응형
Notice
Recent Posts
Recent Comments
Link
«   2025/05   »
1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30 31
Archives
Today
Total
관리 메뉴

테크매니아

Git 로컬 프로토콜과 Git instaweb 본문

카테고리 없음

Git 로컬 프로토콜과 Git instaweb

SciomageLAB 2024. 10. 3. 16:43
반응형

로컬 프로토콜

github, gitlab 같이 호스팅 업체를 통하지 않고 자체적인 서버를 구축하거나 로컬에서만 버전관리를 하거나, FTP 서버 같이 공유 드라이브를 마운팅해서 사용하는 경우에는 file: 프로토콜을 기반으로 동작시킬 수도 있다. bare저장소는 .git 폴더만 갖고 있는 working directory가 아닌 저장소를 의미한다. 내용물이 없고 변경 사항만을 가지고 있는 저장소다.

로컬 기반으로 버전관리를 하려면 먼저 리모트에 해당할 bare 저장소를 만든다.

mkdir SampleLocalHost.git
cd SampleLocalHost.git
git init --bare

# 위 명령어를 치고 나면 버전이 기록에 필요한 파일들이 생성된다.
# HEAD  branches  config  description  hooks  info  objects  refs

이제 커밋할 저장소를 테스트로 하나 만든 뒤 커밋 후 푸시를 해본다.

mkdir SampleProject
touch samplefile.txt
git remote add local /home/dsparch/SampleLocalHost.git
git commit -m initial commit
git push local master

# 푸시 후 출력
dsparch@DESKTOPJSC$ git push local master
Enumerating objects: 3, done.
Counting objects: 100% (3/3), done.
Delta compression using up to 16 threads
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 220 bytes | 220.00 KiB/s, done.
Total 3 (delta 0), reused 0 (delta 0)
To /home/dsparch/SampleLocalHost.git
 * [new branch]      master -> master

로컬 기반으로도 푸시가 되는 것을 확인할 수 있다!. 파일 프로토콜 기반으로 bare와 저장소 간 커밋 푸시는 가능해졌으니 편리한 인터페이스를 제공하는 git instaweb 명령어를 통해 github처럼 커밋 로그를 웹으로 확인해볼 수 있다.

git instaweb wsl2에서 브라우저 띄우기

git instaweb은 lighttpd가 깔려있으면 기본으로 lighttpd를 사용한다. lighttpd는 이름 그래도 엄청 가볍고 고성능인 was인데 nginx보다 가볍다는 의견들이 있다. apache, nginx, webrick 등등 사용자가 가지고 있는 환경에 맞게 -d 옵션으로 사용하고자 하는 httpd를 지정해주면 된다.

사전 설치 : lighttpd 설치하기

sudo apt install lighttpd
sudo apt install libcgi-pm-perl gamin

파워쉘을 이용하여 포트포워딩과 방화벽 해제해주기

WSL2는 가상 머신이기 때문에 가상 네트워크 어댑터를 받는다. 그래서 ip주소도 호스트인 윈도우와 당연히 다르기 때문에 웹서버같은 것을 띄워 확인하려면 포트포워딩을 해줘야 한다.

아래 파워쉘 스크립트를 메모장에 붙여넣고 파워쉘에서 실행시키면 된다.

If (-NOT ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] Administrator)) {   
  $arguments = & ' + $myinvocation.mycommand.definition + '
  Start-Process powershell -Verb runAs -ArgumentList $arguments
  Break
}

$remoteport = bash.exe -c ifconfig eth0 | grep 'inet '
$found = $remoteport -match '\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}';

if ($found) {
  $remoteport = $matches[0];
}
else {
  Write-Output IP address could not be found;
  exit;
}

$ports = @(22, 3000);

for ($i = 0; $i -lt $ports.length; $i++) {
  $port = $ports[$i];
  Invoke-Expression netsh interface portproxy delete v4tov4 listenport=$port;
  Invoke-Expression netsh advfirewall firewall delete rule name=$port;

  Invoke-Expression netsh interface portproxy add v4tov4 listenport=$port connectport=$port connectaddress=$remoteport;
  Invoke-Expression netsh advfirewall firewall add rule name=$port dir=in action=allow protocol=TCP localport=$port;
}

Invoke-Expression netsh interface portproxy show v4tov4;

wsl-forward-server.ps1으로 파일을 저장했고, 파워쉘을 관리자 권한으로 켠 뒤 스크립트를 실행시킨다.

PS C:\Users\dspar> .\wsl-forward-server.ps1

포트포워딩이 잘 됬는 지 확인하려면 netsh 명령어를 아래처럼 ipv4 포트포워딩 된 내용이 나온다. 3, 4번째 열이 WSL의 ip 주소이다.

PS C:\Users\dspar> netsh interface portproxy show v4tov4

ipv4 수신 대기:             ipv4에 연결:

주소            포트        주소            포트
--------------- ----------  --------------- ----------
0.0.0.0         80          172.29.226.17   80
0.0.0.0         443         172.29.226.17   443
0.0.0.0         10000       172.29.226.17   10000
0.0.0.0         3000        172.29.226.17   3000
0.0.0.0         5000        172.29.226.17   5000

웹 브라우저 띄워보기

dspbsd@DESKTOPJSC$ git instaweb -p 3000
Instance already running. Restarting...
No known browser available.
http://127.0.0.1:3000

프로젝트 커밋 목록이 보인다. snapshot을 눌르면 snapshot된 프로젝트 폴더를 다운 받을 수 있다.
굉장히 요긴하다.

파일 프로토콜 말고 git 프로토콜 사용은?

git daemon 명령어를 이용하면 된다. git 데몬을 띄우면 지정된 경로의 리포지토리를 협업자가 git 프로토콜로 클론하고 푸시할 수 있도록 해준다. 기본 9418 포트에서 동작하고, 인증 절차를 제공하지 않기 때문에 사내에서 임시로 운영하는 경우에 쓰면 좋을 것 같다.

로컬 프로토콜 또는 로컬 깃 데몬은 언제 사용하기 좋을까?

정부기관이나 제조 기반의 대기업들은 보안 때문에 폐쇄망인 경우가 많아서 절차가 엄격한 경우는 현장에 가서 README 같은데 모든 전날 작업 로그를 적어놓고 cp해놓고 나오는 경우가 많은데 로컬 기반으로 GUI도 뜨고 버전 관리도 할 수 있어서 폐쇄망 환경에서는 좋은 솔루션이 될 것 같다.

참고: Copy말고 경로로 git clone ./path/ 해서 여러명이 작업하기

bare 저장소도 만들고, 기본 저장소도 만든 뒤 로컬 파일 기반 경로로 clone하여 마치 fork한 것처럼 운용할 수 있다. 폐쇄망에 여러명의 작업자가 함께 하는 경우 리드 개발자가 bare와 원본 저장소를 만들고 다른 작업자들이 clone해가면 분리된 작업환경에서 일하므로 파일이 충돌나거나 사라지거나 할 위험이 줄어든다. request-pull 명령어를 이용하여 각자 작업 후 변경, merge 하면 로컬 폐쇄망에서도 깔끔한 작업이 가능하다.

request-pull은 뭔데?

github의 PR 기능보다 조상님격인 기능으로 변경사항 (patch)가 발생하면 원본 저장소에 반영해달라는 요청을 보내는 명령어이다. 남의 저장소 clone(fork) 해놓고 함부로 패치내역을 당연히 반영할 수 가 없으니 우선 요청을 보낸다. request-pull명령어를 실행하면 요청도 가고 패치에 대한 내용도 출력이 되는데 이 패치를 git send-email이나 hook을 이용해서 관련자들에게 내용을 알리면 된다.

저장소의 관리자는 패치의 내용이 합당하면 작업자의 저장소 URL을 remote add 시켜놓고 pull을 받으면 된다. 물론 막 받으면 좀 그러니 이때 stash 기능을 활용하면 좋다.

운용 방법을 정리하면, 먼저 원본 저장소에서 clone을 하여 작업자가 작업을 한 뒤 커밋 후 request-pull 명령어를 써서 패치를 적용해달라는 요청을 보낸다. 관리자는 fork한 작업자의 저장소 주소를 remote에 add하여 pull을 받으면 된다.

request-pull 명령어 -p 옵션을 주어 패치 내요을 출력하게 하면 다음과 같다. 보면 작업자와 변경 내용이 나오게 된다.

dspbsd@DESKTOPJSC$ git request-pull -p origin/master ./
warn: refs/heads/master found at ./ but points to a different object
warn: Are you sure you pushed 'HEAD' there?
The following changes since commit a2c5c7f77d41b5893ae36f61e258cc05aa67c22e:

  Add simple HTML and stylesheet (2022-02-18 01:07:41 +0900)

are available in the Git repository at:

  ./

for you to fetch changes up to e08e7b22d4ae8764691a15a5767a08de517d2c4e:

  Something changed (2022-02-18 02:03:08 +0900)

----------------------------------------------------------------
Alice (2):
      Change background color to light blue
      Something changed

 CSS/site.css | 2 +-
 index.html   | 1 +
 2 files changed, 2 insertions(+), 1 deletion(-)

diff --git a/CSS/site.css b/CSS/site.css
index 33323b5..7563758 100644
--- a/CSS/site.css
+++ b/CSS/site.css
@@ -1,2 +1,2 @@
 h1, h2, h3, h4, h5, h6 { font-family: sans-serif; }
-body { font-family: serif; }
+body { font-family: serif; background-color: #F0FFF8; }
diff --git a/index.html b/index.html
index 095469d..ebe0340 100644
--- a/index.html
+++ b/index.html
@@ -8,6 +8,7 @@
   <body>
     <h1>Our Feline Friends</h1>
     <p>Eventually we will put cat pictures here.</p>
+    <p>New feature.</p>
     <hr>
   </body>
 </html>

request-pull을 하지 않고 무턱대고 남의 원본 저장소(bare 저장소가 아닌)에 push를 하게되면 아래와 같이 push가 저지된다. 에러 메시지대로 원본 저장소에 몇가지 설정을 해두면 push가 가능하겠지만 추천하지 않는다.

dspbsd@DESKTOPJSC$ git push origin master
Enumerating objects: 5, done.
Counting objects: 100% (5/5), done.
Delta compression using up to 16 threads
Compressing objects: 100% (3/3), done.
Writing objects: 100% (3/3), 313 bytes | 313.00 KiB/s, done.
Total 3 (delta 1), reused 0 (delta 0)
remote: error: refusing to update checked out branch: refs/heads/master
remote: error: By default, updating the current branch in a non-bare repository
remote: is denied, because it will make the index and work tree inconsistent
remote: with what you pushed, and will require 'git reset --hard' to match
remote: the work tree to HEAD.
remote:
remote: You can set the 'receive.denyCurrentBranch' configuration variable
remote: to 'ignore' or 'warn' in the remote repository to allow pushing into
remote: its current branch; however, this is not recommended unless you
remote: arranged to update its work tree to match what you pushed in some
remote: other way.
remote:
remote: To squelch this message and still keep the default behaviour, set
remote: 'receive.denyCurrentBranch' configuration variable to 'refuse'.
To /home/dspbsd/tmp/alice/../Sample/
 ! [remote rejected] master -> master (branch is currently checked out)
error: failed to push some refs to '/home/dspbsd/tmp/alice/../Sample/'

관리자는 메일링을 하면서 패치를 리뷰한 뒤 아래와 같은 과정으로 패치를 적용하면 된다.

git remote add <이름> <작업자 저장소 경로, URL 또는 경로>
git pull <이름> <request온 브랜치>

`

참고: Bare 저장소에 기본 브랜치 설정하기

symbolic-ref 명령어로 HEAD 저장소가 master 브랜치를 기본으로 가리키도록 해주면 bare에서master가 기본 브랜치가 된다. pull 받아갈 때도 기본 브랜치가 되려면 git branch --set-upstream-to 옵션을 사용하면 된다. 아래 두 명령어를 사용하면 기본 브랜치를 master로, 변경사항을 추적하는 브랜치도 master로 하여 clone이나 pull을 받아갈 때 master를 기본 브랜치로 해줄 수 있다.

git symbolic-ref HEAD refs/heads/master
git branch --set-upstream-to origin/main

참고 : 인트라넷 조차도 없는, 네트워크도 안되는 상황에서는 bundle 활용

인트라넷도 아니라서 공유기조차도 없고 블루투스도 없고 뭐도 없어서 파일을 직접 USB로 옮겨올 수만 있는 상황이라면 bundle 명령어를 쓰면 된다.

git bundle create <worktree-name>.bundle HEAD master

bundle 파일을 unbundle해서 clone 또는 pull/fetch 하여 사용할 수 있다. verify 명령어로 새로운 bundle을 합치는데 문제가 없는지 확인하고 문제가 없다면 다음 업데이트 된 bundle로부터 pull을 받아올 수 있다.

git clone repo.bundle repo
git bundle verify ../../repo.bundle
git pull ../../newrepo.bundle
dsparch@DESKTOP-EJ52IEM$ git bundle create repo.bundle HEAD master
Enumerating objects: 20, done.
Counting objects: 100% (20/20), done.
Compressing objects: 100% (13/13), done.
Total 20 (delta 4), reused 0 (delta 0)

dsparch@DESKTOP-EJ52IEM$ git clone ../repo.bundle
Cloning into 'repo'...
Receiving objects: 100% (15/15), done.
Resolving deltas: 100% (2/2), done.

dsparch@DESKTOP-EJ52IEM$ git bundle verify ../../repo.bundle
The bundle contains these 2 refs:
bb9a562fd1e2b0cbcecfbbb5ec6cb016de53b940 HEAD
bb9a562fd1e2b0cbcecfbbb5ec6cb016de53b940 refs/heads/master
The bundle records a complete history.
../../repo.bundle is okay

dsparch@DESKTOP-EJ52IEM$ git remote -v
origin  /home/dsparch/kill/../repo.bundle (fetch)
origin  /home/dsparch/kill/../repo.bundle (push)

dsparch@DESKTOP-EJ52IEM$ git pull ../../repo.bundle
Receiving objects: 100% (20/20), done.
Resolving deltas: 100% (4/4), done.
From ../../repo.bundle
 * branch            HEAD       -> FETCH_HEAD
Updating bb9a562..098d870
Fast-forward
 README.md | 7 +------
 main.c    | 7 ++++---
 2 files changed, 5 insertions(+), 9 deletions(-)

참고자료

git instaweb fails with 500 - Internal Server Error

깃이 지원하는 다양한 전송 프로토콜

반응형