• shallow clone ๋œ ์ €์žฅ์†Œ์— ์ „์ฒด ์ปค๋ฐ‹ ํžˆ์Šคํ† ๋ฆฌ๋ฅผ ๋ณต์›ํ•˜๋Š” git ๋ช…๋ น์–ด.
  • CI/CD ํ™˜๊ฒฝ์—์„œ ๋นŒ๋“œ ์†๋„๋ฅผ ์œ„ํ•ด shallow clone์„ ์‚ฌ์šฉํ•˜์ง€๋งŒ, git ํžˆ์Šคํ† ๋ฆฌ๊ฐ€ ํ•„์š”ํ•œ ์ž‘์—…์—์„œ ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•  ๋•Œ ์‚ฌ์šฉ

ํ•ด๋‹น ๊ฐœ๋…์ด ํ•„์š”ํ•œ ์ด์œ 

  • CI/CD ํ”Œ๋žซํผ(Cloudflare Pages, GitHub Actions, Vercel ๋“ฑ)์€ ๋นŒ๋“œ ์†๋„ ์ตœ์ ํ™”๋ฅผ ์œ„ํ•ด ๊ธฐ๋ณธ์ ์œผ๋กœ git clone --depth 1 (shallow clone)์„ ์ˆ˜ํ–‰
  • shallow clone ์ƒํƒœ์—์„œ๋Š” git log, git blame, ํƒœ๊ทธ ๊ธฐ๋ฐ˜ ๋ฒ„์ „ ๊ณ„์‚ฐ ๋“ฑ ํžˆ์Šคํ† ๋ฆฌ ์˜์กด ์ž‘์—…์ด ์‹คํŒจํ•˜๊ฑฐ๋‚˜ ๋ถ€์ •ํ™•ํ•œ ๊ฒฐ๊ณผ๋ฅผ ๋ฐ˜ํ™˜
  • git fetch --unshallow๋กœ ์ „์ฒด ํžˆ์Šคํ† ๋ฆฌ๋ฅผ ๋ณต์›ํ•˜๋ฉด ์ด๋Ÿฌํ•œ ์ œ์•ฝ์„ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ์Œ

AS-IS: Shallow Clone

sequenceDiagram
    autonumber
    participant CI as CI/CD ํ”Œ๋žซํผ
    participant Git as Git Remote

    CI->>Git: git clone --depth 1
    Note over CI: ์ปค๋ฐ‹ 1๊ฐœ๋งŒ ์กด์žฌ<br/>ํžˆ์Šคํ† ๋ฆฌ ์กฐํšŒ ๋ถˆ๊ฐ€
    CI->>CI: git log โ†’ ์ตœ์‹  ์ปค๋ฐ‹ 1๊ฐœ๋งŒ ๋ฐ˜ํ™˜
    CI->>CI: git log --diff-filter=A โ†’ ๋ถ€์ •ํ™•
    CI->>CI: git describe --tags โ†’ ์‹คํŒจ

TO-BE: unshallow๋กœ ๋ณต์›

sequenceDiagram
    autonumber
    participant CI as CI/CD ํ”Œ๋žซํผ
    participant Git as Git Remote

    CI->>Git: git clone --depth 1
    CI->>Git: git fetch --unshallow
    Note over CI: ์ „์ฒด ์ปค๋ฐ‹ ํžˆ์Šคํ† ๋ฆฌ ๋ณต์›
    CI->>CI: git log โ†’ ์ „์ฒด ํžˆ์Šคํ† ๋ฆฌ ์กฐํšŒ ๊ฐ€๋Šฅ
    CI->>CI: git log --diff-filter=A โ†’ ์ •ํ™•ํ•œ ์ตœ์ดˆ ์ปค๋ฐ‹
    CI->>CI: git describe --tags โ†’ ์ •์ƒ ๋™์ž‘

Shallow Clone์ด๋ž€

git ํžˆ์Šคํ† ๋ฆฌ์˜ ์ผ๋ถ€๋งŒ ๊ฐ€์ ธ์˜ค๋Š” clone ๋ฐฉ์‹์ด๋‹ค.

git clone --depth 1  # ์ตœ์‹  ์ปค๋ฐ‹ 1๊ฐœ๋งŒ
git clone --depth 5  # ์ตœ์‹  ์ปค๋ฐ‹ 5๊ฐœ๋งŒ
git clone            # ์ „์ฒด ํžˆ์Šคํ† ๋ฆฌ (full clone)

์žฅ์ : clone ์†๋„๊ฐ€ ๋น ๋ฅด๊ณ  ๋””์Šคํฌ ์‚ฌ์šฉ๋Ÿ‰์ด ์ ์Œ ๋‹จ์ : ํžˆ์Šคํ† ๋ฆฌ ์˜์กด ์ž‘์—…์ด ๋ถˆ๊ฐ€๋Šฅํ•˜๊ฑฐ๋‚˜ ๋ถ€์ •ํ™•

shallow clone์—์„œ ์‹คํŒจํ•˜๋Š” ์ž‘์—…๋“ค

์ž‘์—…๋ช…๋ น์–ด์‹คํŒจ ์›์ธ
ํŒŒ์ผ ์ตœ์ดˆ ์ƒ์„ฑ์ผ ์กฐํšŒgit log --diff-filter=Aํžˆ์Šคํ† ๋ฆฌ๊ฐ€ ์—†์–ด ์ตœ์ดˆ ์ปค๋ฐ‹์„ ์ฐพ์„ ์ˆ˜ ์—†์Œ
์ฝ”๋“œ blamegit blame์ž‘์„ฑ์ž/์‹œ์  ์ถ”์  ๋ถˆ๊ฐ€
ํƒœ๊ทธ ๊ธฐ๋ฐ˜ ๋ฒ„์ „git describe --tagsํƒœ๊ทธ๊ฐ€ shallow ๋ฒ”์œ„ ๋ฐ–์ด๋ฉด ์‹คํŒจ
์ปค๋ฐ‹ ์ˆ˜ ๊ณ„์‚ฐgit rev-list --count๋ถ€์ •ํ™•ํ•œ ๊ฒฐ๊ณผ

git fetch โ€”unshallow ๋™์ž‘ ์›๋ฆฌ

git fetch --unshallow
  • shallow clone ์ƒํƒœ์—์„œ๋งŒ ๋™์ž‘ (์ด๋ฏธ full clone์ด๋ฉด ์—๋Ÿฌ)
  • remote์—์„œ ๋‚˜๋จธ์ง€ ๋ชจ๋“  ์ปค๋ฐ‹ ํžˆ์Šคํ† ๋ฆฌ๋ฅผ ์ถ”๊ฐ€๋กœ fetch
  • ์‹คํ–‰ ํ›„ .git/shallow ํŒŒ์ผ์ด ์ œ๊ฑฐ๋˜๋ฉฐ full clone๊ณผ ๋™์ผํ•œ ์ƒํƒœ๊ฐ€ ๋จ

๊ด€๋ จ ๋ช…๋ น์–ด ๋น„๊ต:

๋ช…๋ น์–ด์šฉ๋„
git clone --depth 1์ตœ์‹  ์ปค๋ฐ‹ 1๊ฐœ๋งŒ clone
git fetch --unshallowshallow โ†’ full clone์œผ๋กœ ํ™•์žฅ
git fetch --depth Nshallow ๊นŠ์ด๋ฅผ N์œผ๋กœ ์กฐ์ •

์‹ค์ œ ์‚ฌ๋ก€: Quartz ๋‚ ์งœ๋ณ„ ๋ณด๊ธฐ

๋ฐฐ๊ฒฝ

Quartz ์ •์  ์‚ฌ์ดํŠธ์˜ โ€œ๋‚ ์งœ๋ณ„ ๋ณด๊ธฐ(DateIndex)โ€œ์—์„œ ํŒŒ์ผ์„ ์ƒ์„ฑ ๋‚ ์งœ ๊ธฐ์ค€์œผ๋กœ ๊ทธ๋ฃนํ•‘ํ•˜๋ ค๊ณ  ํ–ˆ๋‹ค.

Quartz ๊ธฐ๋ณธ ์ œ๊ณต ํ”Œ๋Ÿฌ๊ทธ์ธ CreatedModifiedDate(lastmod.ts)๊ฐ€ ํŒŒ์ผ์˜ ๋‚ ์งœ๋ฅผ ๊ฒฐ์ •ํ•œ๋‹ค:

// quartz.config.ts
Plugin.CreatedModifiedDate({
  priority: ["frontmatter", "git", "filesystem"],
})
์šฐ์„ ์ˆœ์œ„์†Œ์Šคcreatedmodified
1frontmattercreated ํ•„๋“œmodified ํ•„๋“œ
2git์ตœ์ดˆ ์ปค๋ฐ‹ ๋‚ ์งœ์ตœ๊ทผ ์ปค๋ฐ‹ ๋‚ ์งœ
3filesystembirthtimeMsmtimeMs

๋ฌธ์ œ 1: ํ”Œ๋Ÿฌ๊ทธ์ธ์ด git์—์„œ created๋ฅผ ๊ฐ€์ ธ์˜ค์ง€ ์•Š์Œ

์›๋ž˜ CreatedModifiedDate ํ”Œ๋Ÿฌ๊ทธ์ธ์€ git์—์„œ modified๋งŒ ๊ฐ€์ ธ์™”๋‹ค:

// ์›๋ณธ - git์—์„œ modified๋งŒ ์กฐํšŒ
modified ||= await repo.getFileLatestModifiedDateAsync(relativePath)
// created๋Š” ์กฐํšŒํ•˜์ง€ ์•Š์Œ

Obsidian์—์„œ ์ž‘์„ฑํ•œ ํŒŒ์ผ ์ค‘ frontmatter์— created๊ฐ€ ์—†๋Š” ํŒŒ์ผ์ด ์กด์žฌํ•˜์—ฌ, git โ†’ filesystem์œผ๋กœ fallback๋˜์—ˆ๋‹ค.

์ˆ˜์ •: git log --diff-filter=A๋กœ ์ตœ์ดˆ ์ปค๋ฐ‹ ๋‚ ์งœ๋ฅผ created๋กœ ์„ค์ •ํ•˜๋Š” ๋กœ์ง ์ถ”๊ฐ€:

// ์ˆ˜์ • - git์—์„œ created๋„ ์กฐํšŒ
modified ||= await repo.getFileLatestModifiedDateAsync(relativePath)
 
if (!created) {
  const result = execSync(
    `git log --follow --diff-filter=A --format=%at -- "${relativePath}"`,
    { cwd: repositoryWorkdir, encoding: "utf-8" },
  ).trim()
  if (result) {
    created = parseInt(result) * 1000
  }
}
  • --follow: ํŒŒ์ผ๋ช… ๋ณ€๊ฒฝ ์ถ”์ 
  • --diff-filter=A: โ€œAddedโ€ ์ปค๋ฐ‹๋งŒ ํ•„ํ„ฐ๋ง
  • --format=%at: Unix timestamp ์ถœ๋ ฅ
  • ๋นŒ๋“œ ํƒ€์ž„์— ์ •์  ๊ณ„์‚ฐ โ†’ ๋Ÿฐํƒ€์ž„ ์„ฑ๋Šฅ ์˜ํ–ฅ ์—†์Œ

๋ฌธ์ œ 2: Cloudflare Pages shallow clone

์ฝ”๋“œ๋ฅผ ์ˆ˜์ •ํ•ด๋„ Cloudflare Pages ๋นŒ๋“œ ํ™˜๊ฒฝ์—์„œ 44๊ฐœ ํŒŒ์ผ์ด ๊ฐ™์€ ๋‚ ์งœ๋กœ ํ‘œ์‹œ๋˜์—ˆ๋‹ค.

์›์ธ: Cloudflare Pages๊ฐ€ --depth 1 shallow clone์„ ์‚ฌ์šฉํ•˜์—ฌ:

1. frontmatter.created โ†’ ์—†๋Š” ํŒŒ์ผ ์กด์žฌ (undefined)
2. git log --diff-filter=A โ†’ ์ปค๋ฐ‹ 1๊ฐœ๋ฟ์ด๋ผ ๋ถ€์ •ํ™•
3. filesystem birthtimeMs โ†’ clone ์‹œ์  = ๋ชจ๋“  ํŒŒ์ผ ๋™์ผ ๋‚ ์งœ

ํ•ด๊ฒฐ: ๋นŒ๋“œ ๋ช…๋ น์–ด์— git fetch --unshallow ์ถ”๊ฐ€:

# ๋ณ€๊ฒฝ ์ „
npm ci && npx quartz build

# ๋ณ€๊ฒฝ ํ›„
git fetch --unshallow && npm ci && npx quartz build

์„ค์ • ์œ„์น˜: Cloudflare Dashboard โ†’ Workers & Pages โ†’ ํ”„๋กœ์ ํŠธ โ†’ Settings โ†’ Build command

์ฐธ๊ณ  ๋ฌธ์„œ