Programming

GitLab 서버로부터 여러 프로젝트의 일부 디렉토리만 Checkout 하기

Gadget 2025. 8. 4. 10:18

1. gitlab 서버에 ssh key 미리 등록 (Settings - SSH Keys)

2. 아래 스크립트(git_clone.sh 등으로)를 소스를 내려받을 서버에 저장 (상단의 환경변수는 적절히 변경 필요)

3. Jenkins 등의 도구에서 스크립트 호출하여 checkout

가령, myprogram 이란 빌드가 있고, res/image res/js java lib 등의 프로젝트/디렉토리로 분리되어 있는 경우,

git_clone.sh myprogram res/image res/js java lib 과 같이 실행하면,

작업디렉토리/myprogram/src 아래에 지정한 프로젝트/디렉토리만 checkout 됩니다.

 

[git_clone.sh]

#!/bin/bash

if [ $# -lt 2 ]; then
    echo "Usage: $0 <build_target> <project1/directory> <project2/directory> <project3> ..."
    echo "ex) $0 빌드대상 프로젝트1/디렉토리 프로젝트2/디렉토리 프로젝트3"
    exit 1
fi

WORK_DIR="작업디렉토리/$1/src"
HASH_DIR="작업디렉토리/data"
HASH_FILE="$HASH_DIR/$1.hash"
HASH_FILE_NEW="$HASH_DIR/$1.new_hash"
GIT_REPO="GIT서버계정명@GIT서버IP:GIT레파지토리명"
shift

/usr/bin/rm -rf "$WORK_DIR"
mkdir -p "$WORK_DIR"
cd "$WORK_DIR"

/usr/bin/rm -f "$HASH_FILE_NEW"

for ENTRY in "$@"; do
  if [[ "$ENTRY" == */* ]]; then
    PROJ_NAME="${ENTRY%%/*}"
    SPARSE_PATH="${ENTRY#*/}"
  else
    PROJ_NAME="$ENTRY"
    SPARSE_PATH=""
  fi

  REPO_DIR="$WORK_DIR/$PROJ_NAME"
  
  if [ ! -d "$REPO_DIR/.git" ]; then
    git clone --no-checkout "$GIT_REPO/${PROJ_NAME}.git" "$REPO_DIR" || {
      continue
    }
  else
    cd "$REPO_DIR" || continue
    git fetch origin
    cd "$WORK_DIR" || exit 1
  fi
  
  cd "$REPO_DIR" || continue
  
  git sparse-checkout init --cone
  
  if [ -n "$SPARSE_PATH" ]; then
    git sparse-checkout set "$SPARSE_PATH"
  else
    git sparse-checkout disable
  fi
  
  branch_name=$(git symbolic-ref --short refs/remotes/origin/HEAD | sed 's|origin/||')
  echo "Checking out branch: $branch_name"
  git checkout "$branch_name"

  if [ -f "$HASH_FILE" ]; then
    OLD_HASH=$(grep "^$ENTRY[[:space:]]" "$HASH_FILE" | awk '{print $2}')
    echo "[OLD HASH]: $OLD_HASH"
  else
    OLD_HASH=""
  fi
  NEW_HASH=$(git rev-parse HEAD)
  echo "[NEW HASH]: $NEW_HASH"

  if [ -z "$OLD_HASH" ]; then
    echo "=== Commit Message ==="
    git show --oneline -s "$NEW_HASH" | iconv -f UTF-8 -t EUC-KR
    echo
  elif [ "$NEW_HASH" != "$OLD_HASH" ]; then
    echo "=== Changed files since previous deploy / Commit Message ==="
    git diff --name-only --oneline "$OLD_HASH" "$NEW_HASH" | iconv -f UTF-8 -t EUC-KR
    echo
  else
    echo "=== Not changed ==="
  fi
  
  mkdir -p "$HASH_DIR"
  echo "$ENTRY" "$NEW_HASH" >> "$HASH_FILE_NEW"

  cd "$WORK_DIR" || exit 1
done

mv -f "$HASH_FILE_NEW" "$HASH_FILE"