Skip to content

Commit 68bcf87

Browse files
Round 1 deepen: gitlab-tech-zh-tw — advanced examples, deeper theory, diagnostics, challenge exercises
1 parent 4051643 commit 68bcf87

8 files changed

Lines changed: 561 additions & 0 deletions

docs/unit-01-gitlab-intro.html

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,67 @@ <h2>延伸閱讀</h2>
139139
<div class="next-prev">
140140
<a class="np-next" href="unit-02-first-project.html"><div class="np-label">下一篇 →</div><div class="np-name">單元 2 · 第一個專案</div></a>
141141
</div>
142+
143+
<!-- ═══════ Round 1 Deepen ═══════ -->
144+
<h2>進階真實情境 Worked Example</h2>
145+
<h3>情境:選擇 GitLab 自架部署企業內部 DevOps 環境</h3>
146+
<p>一家受金融法規規範的科技公司,要求「所有原始碼與 CI/CD 流程不得離開公司網路」。團隊決定自架 GitLab CE,並在同一台主機安裝 GitLab Runner,使用 Docker executor 執行 CI jobs。</p>
147+
<div class="demo-block">
148+
<div class="demo-label">安裝流程 · DEPLOY</div>
149+
<pre><span class="hl-c"># 1. 安裝 Docker(Ubuntu)</span>
150+
sudo apt update && sudo apt install docker.io -y
151+
152+
<span class="hl-c"># 2. 用 Docker 單鍵部署 GitLab CE</span>
153+
sudo docker run -d \
154+
--hostname gitlab.example.com \
155+
--name gitlab \
156+
-p 80:80 -p 443:443 -p 2222:22 \
157+
-v /srv/gitlab/config:/etc/gitlab \
158+
-v /srv/gitlab/logs:/var/log/gitlab \
159+
-v /srv/gitlab/data:/var/opt/gitlab \
160+
gitlab/gitlab-ce:latest
161+
162+
<span class="hl-c"># 3. 等待啟動完成後,取得 root 初始密碼</span>
163+
sudo docker exec gitlab cat /etc/gitlab/initial_root_password
164+
165+
<span class="hl-c"># 4. 註冊 Runner(群組層級,Docker executor)</span>
166+
sudo docker exec -it gitlab gitlab-runner register \
167+
--url https://gitlab.example.com \
168+
--token GROUP_REGISTRATION_TOKEN \
169+
--executor docker \
170+
--docker-image node:20
171+
172+
<span class="hl-c"># 5. 驗證:在專案中建立 .gitlab-ci.yml,push 後觀察 pipeline</span></pre>
173+
</div>
174+
<div class="callout"><strong>設計決策:</strong>① 用 Docker volume 掛載三個目錄確保資料持久化;② Runner 用 Docker executor 讓每個 job 在獨立容器中執行,互不污染;③ 2222 port 映射避免與主機 SSH 衝突。</div>
175+
176+
<h2>深入原理擴充</h2>
177+
<h3>GitLab 與 Git 的分工:伺服器端運作</h3>
178+
<p>Git 是命令列工具,GitLab 是 Rails 應用。GitLab 伺服器端透過 <strong>Gitolite</strong> 或自研的 <strong>Gitaly</strong>(gRPC 服務)管理 Git 倉庫的存取控制與操作。</p>
179+
<table>
180+
<tr><th>元件</th><th>職責</th><th>容易誤解的點</th></tr>
181+
<tr><td><strong>Gitaly</strong></td><td>Git 倉庫的 gRPC 存取層(clone、push、diff 等)</td><td>GitLab 不是直接呼叫 git 命令列,而是透過 Gitaly 服務化</td></tr>
182+
<tr><td><strong>Praefect</strong></td><td>Gitaly 代理,支援多副本與 failover</td><td>這是 GitLab 14+ 的高可用方案,自架時預設不開啟</td></tr>
183+
<tr><td><strong>GitLab Shell</strong></td><td>處理 SSH 存取(push/pull)</td><td>SSH 只是 Git 操作的通道,CI/CD 與 Web 操作不經 GitLab Shell</td></tr>
184+
</table>
185+
<div class="callout info"><strong>關鍵:</strong>你在 GitLab 網頁上看到的「儲存庫大小」包含 Git 物件、LFS、Wiki 等,但不含 CI artifacts 與 Container Registry——這兩者各有獨立儲存。</div>
186+
187+
<h2>診斷式疑難排解表</h2>
188+
<table>
189+
<tr><th>症狀</th><th>可能原因</th><th>解決方案</th></tr>
190+
<tr><td>git clone / push 報 403 Forbidden</td><td>PAT 未勾選 write_repository scope 或已過期</td><td>到 Settings → Access Tokens 確認 scope 與到期日,重新產生 token</td></tr>
191+
<tr><td>自架 GitLab 網頁打不開</td><td>Docker port 映射錯誤,或主機防火牆擋住 80/443</td><td>執行 <code>docker ps</code> 確認 port,檢查 <code>ufw status</code> 或 iptables 規則</td></tr>
192+
<tr><td>SSH clone 報錯「Permission denied (publickey)」</td><td>SSH key 未上傳到 GitLab,或本地 ssh-agent 未載入</td><td>確認 <code>~/.ssh/id_rsa.pub</code> 已加到 GitLab → Preferences → SSH Keys,並執行 <code>ssh-add</code></td></tr>
193+
<tr><td>git pull 後衝突標記未消失</td><td>沒有實際執行 git add 與 git commit 解決衝突</td><td>編輯衝突檔案 → <code>git add .</code><code>git commit -m "resolve conflict"</code></td></tr>
194+
<tr><td>Internal visibility 專案看不見</td><td>使用 GitLab.com(非自架),Internal 級別不可用</td><td>GitLab.com 只有 Public / Private;Internal 是自架專屬功能</td></tr>
195+
</table>
196+
197+
<h2>進階挑戰題</h2>
198+
<ol>
199+
<li><strong>多 Runner 策略設計:</strong>為一個有前端(Node)與後端(Python)的專案,設計 Runner tag 策略,讓前端 job 只跑在有 Node 環境的 Runner,後端 job 只跑在有 Python 的 Runner。畫出架構圖並說明 tag 的設定方式。</li>
200+
<li><strong>GitLab CE vs EE 功能差距分析:</strong>調查三個 GitLab EE 獨有的功能(如 Audit Events、Merge Train、Code Owners),說明它們在 50 人以上的團隊中如何提升合規性與效率。</li>
201+
</ol>
202+
142203
</div>
143204
<footer>這是 GitLab 繁體中文教學站 · 由 OpenCode 建置<br>
144205
<span class="footer-license">本站教學內容(繁體中文解說)為本站原創,採 CC-BY-4.0;技術名詞與操作引用自 <a href="https://docs.gitlab.com/" rel="noopener">GitLab Docs</a><a href="https://git-scm.com/doc" rel="noopener">Git 官方文件</a></span></footer>

docs/unit-02-first-project.html

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,61 @@ <h2>延伸閱讀</h2>
153153
<a href="unit-01-gitlab-intro.html"><div class="np-label">← 上一篇</div><div class="np-name">單元 1 · GitLab 是什麼</div></a>
154154
<a class="np-next" href="unit-03-branches-mr.html"><div class="np-label">下一篇 →</div><div class="np-name">單元 3 · 分支與 Merge Request</div></a>
155155
</div>
156+
157+
<!-- ═══════ Round 1 Deepen ═══════ -->
158+
<h2>進階真實情境 Worked Example</h2>
159+
<h3>情境:建立多專案群組並用 Group Runner 自動化 CI</h3>
160+
<p>一個 15 人團隊,需要三個專案(前端、後端、共用函式庫),全部放在同一個群組下,共用一組自架 Runner。</p>
161+
<div class="demo-block">
162+
<div class="demo-label">群組架構 · GROUP TREE</div>
163+
<pre>myorg/ ← Group
164+
├── frontend-app ← Project(Visibility: Private)
165+
├── backend-api ← Project(Visibility: Private)
166+
├── shared-ui-lib ← Project(Visibility: Internal,全公司可讀)
167+
└── myorg.gitlab.io ← Project(Visibility: Public,對外入口)
168+
169+
<span class="hl-c"># Group Runner 註冊(在群組設定頁取得 token)</span>
170+
sudo gitlab-runner register \
171+
--url https://gitlab.example.com \
172+
--token &lt;GROUP_TOKEN&gt; \
173+
--executor docker \
174+
--tag-list "myorg" \
175+
--run-untagged="false"
176+
177+
<span class="hl-c"># 權限設計:</span>
178+
<span class="hl-c"># Owner → 技術主管(2人)</span>
179+
<span class="hl-c"># Maintainer → Team Lead(3人)</span>
180+
<span class="hl-c"># Developer → 開發者(10人)</span></pre>
181+
</div>
182+
<div class="callout"><strong>設計決策:</strong>① 共用函式庫設 Internal 讓公司內其他團隊可讀但不能改;② Runner 用 tag 過濾,只有 myorg 群組的專案才能使用此 Runner;③ 權限向下繼承:在 Group 設 Developer,三個專案自動都是 Developer。</div>
183+
184+
<h2>深入原理擴充</h2>
185+
<h3>Namespace 與路由解析</h3>
186+
<p>GitLab 的 URL 路徑對應到內部的 <strong>Namespace</strong>(命名空間)。一個專案的完整路徑是 <code>namespace/project</code>,其中 namespace 可以是 User 或 Group。</p>
187+
<table>
188+
<tr><th>URL 路徑</th><th>Namespace 類型</th><th>專案歸屬</th></tr>
189+
<tr><td>gitlab.com/alice/hello</td><td>User(alice)</td><td>個人專案</td></tr>
190+
<tr><td>gitlab.com/myorg/backend-api</td><td>Group(myorg)</td><td>群組專案</td></tr>
191+
<tr><td>gitlab.com/myorg/platform/backend-api</td><td>Subgroup(myorg/platform)</td><td>子群組專案</td></tr>
192+
</table>
193+
<div class="callout warn"><strong>容易搞錯:</strong>Transfer 專案到新群組時,所有 clone URL 會變——已通知團隊更新 remote,否則下次 push 會失敗。</div>
194+
195+
<h2>診斷式疑難排解表</h2>
196+
<table>
197+
<tr><th>症狀</th><th>可能原因</th><th>解決方案</th></tr>
198+
<tr><td>git push 顯示「remote: The project you were looking for could not be found」</td><td>遠端 URL 路徑錯誤(例如群組名拼錯)</td><td>執行 <code>git remote -v</code> 確認 URL,用 <code>git remote set-url origin</code> 修正</td></tr>
199+
<tr><td>看不到 Internal 專案</td><td>你在 GitLab.com(非自架),或帳號未登入</td><td>Internal 只在自架環境有效;確認已登入該 GitLab 實例</td></tr>
200+
<tr><td>Subgroup 裡的專案權限不符預期</td><td>Subgroup 有獨立的權限設定,覆蓋了上層 Group 的繼承</td><td>檢查 Subgroup → Members,確認是否有人為覆寫</td></tr>
201+
<tr><td>git clone 报 SSL certificate problem</td><td>自架 GitLab 使用自簽憑證,本機不信任</td><td>執行 <code>git config --global http.sslVerify false</code>(開發用),或匯入公司 CA 憑證</td></tr>
202+
<tr><td>專案路徑中有大寫字母被拒絕</td><td>GitLab slug 只允許小寫英文、數字、連字號、底線</td><td>專案名稱可含大寫,但路徑 slug 會自動轉小寫;建專案時直接用小寫命名</td></tr>
203+
</table>
204+
205+
<h2>進階挑戰題</h2>
206+
<ol>
207+
<li><strong>群組權限例外設計:</strong>一個 30 人的群組中,有 2 個專案需要「外部承包商」也能 push(Developer),但承包商不能看到其他專案。設計權限方案並說明如何用 Subgroup 或專案層級覆寫達成。</li>
208+
<li><strong>從 GitHub 遷移到 GitLab:</strong>描述完整遷移步驟(含 Issues、MR、Label),並列出三個遷移後需要檢查的項目(CI 設定、Webhook、Protected Branches)。</li>
209+
</ol>
210+
156211
</div>
157212
<footer>這是 GitLab 繁體中文教學站 · 由 OpenCode 建置<br>
158213
<span class="footer-license">本站教學內容(繁體中文解說)為本站原創,採 CC-BY-4.0;技術名詞與操作引用自 <a href="https://docs.gitlab.com/" rel="noopener">GitLab Docs</a><a href="https://git-scm.com/doc" rel="noopener">Git 官方文件</a></span></footer>

docs/unit-03-branches-mr.html

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,64 @@ <h2>延伸閱讀</h2>
157157
<a href="unit-02-first-project.html"><div class="np-label">← 上一篇</div><div class="np-name">單元 2 · 第一個專案</div></a>
158158
<a class="np-next" href="unit-04-merge-request.html"><div class="np-label">下一篇 →</div><div class="np-name">單元 4 · Merge Request 深入</div></a>
159159
</div>
160+
161+
<!-- ═══════ Round 1 Deepen ═══════ -->
162+
<h2>進階真實情境 Worked Example</h2>
163+
<h3>情境:GitFlow 工作流——多分支長期專案</h3>
164+
<p>一個 SaaS 產品同時維護三個版本(v1.x、v2.x、v3.x),需要 develop、release、hotfix 等分支策略。</p>
165+
<div class="demo-block">
166+
<div class="demo-label">GitFlow 分支圖 · FLOW</div>
167+
<pre>main ─────●────●────●─────────●───●───────────
168+
│ │ │ │ │
169+
release/1 │ │ ●────●───┘ │ ← 釋出分支
170+
│ │ ↑ ↑ │
171+
develop ───●────●────●────●────●──●───●───────
172+
↑ ↑ ↑ ↑
173+
feature/a ────●────●────┘ │ │
174+
feature/b ──────────────────────●────┘
175+
hotfix/1 ─────────────────────────────●────── ← 緊急修復
176+
177+
<span class="hl-c"># 1. 從 develop 開 feature</span>
178+
git checkout -b feature/search develop
179+
<span class="hl-c"># 開發完成 → MR target: develop</span>
180+
181+
<span class="hl-c"># 2. 準備發版:從 develop 開 release</span>
182+
git checkout -b release/2.1 develop
183+
<span class="hl-c"># 只做 bugfix → MR target: main + develop</span>
184+
185+
<span class="hl-c"># 3. 緊急修復:從 main 開 hotfix</span>
186+
git checkout -b hotfix/crash-fix main
187+
<span class="hl-c"># 修完 → MR target: main + develop</span></pre>
188+
</div>
189+
<div class="callout"><strong>關鍵:</strong>hotfix 與 release 分支都需要「雙向合併」——合併到 main 後也要同步回 develop,否則下次 develop 的版本會缺少修復。</div>
190+
191+
<h2>深入原理擴充</h2>
192+
<h3>Git 合併策略的底層邏輯</h3>
193+
<p>Git 支援多種合併策略,影響衝突解決方式與歷史圖形:</p>
194+
<table>
195+
<tr><th>策略</th><th>指令</th><th>特點</th><th>何時使用</th></tr>
196+
<tr><td><strong>merge(預設)</strong></td><td><code>git merge branch</code></td><td>產生合併 commit(兩條線匯合)</td><td>保留完整開發過程</td></tr>
197+
<tr><td><strong>squash merge</strong></td><td><code>git merge --squash branch</code></td><td>把分支所有 commit 壓成一個</td><td>歷史要乾淨</td></tr>
198+
<tr><td><strong>rebase</strong></td><td><code>git rebase main</code></td><td>把分支 commit「重放」到 main 最新位置,無合併節點</td><td>直線歷史</td></tr>
199+
</table>
200+
<div class="callout warn"><strong>黃金準則:</strong><strong>永遠不要 rebase 已經 push 到遠端的分支</strong>——rebase 會改寫 commit hash,其他人的本地副本會產生分歧,導致混亂。只 rebase 你自己的、尚未分享的分支。</div>
201+
202+
<h2>診斷式疑難排解表</h2>
203+
<table>
204+
<tr><th>症狀</th><th>可能原因</th><th>解決方案</th></tr>
205+
<tr><td>git merge 報「CONFLICT (content)」但找不到衝突檔案</td><td>衝突在子模組(submodule)或二進位檔中</td><td>執行 <code>git diff --name-only --diff-filter=U</code> 列出所有衝突檔案</td></tr>
206+
<tr><td>rebase 後 git push 被拒絕</td><td>已 rebase 了已 push 的分支(歷史被改寫)</td><td>確認沒其他人在此分支工作;若已推送需 <code>git push --force-with-lease</code>,並通知團隊</td></tr>
207+
<tr><td>MR 合併後衝突又出現</td><td>target 分支在 MR 開發期間又有新 commit,未 rebase/merge 最新 main</td><td>在合併前先 <code>git checkout feature && git rebase main</code>,解決衝突後再 push</td></tr>
208+
<tr><td>git log 圖形很亂、看不清分支關係</td><td>大量 merge commit 造成交叉線</td><td>執行 <code>git log --oneline --graph --all</code>;或改用 squash merge 減少合併節點</td></tr>
209+
<tr><td>分支名稱含斜線(feature/login)本地切換失敗</td><td>shell 把 / 當成路徑分隔符</td><td>引用時加引號:<code>git checkout "feature/login"</code> 或用 <code>git switch feature/login</code></td></tr>
210+
</table>
211+
212+
<h2>進階挑戰題</h2>
213+
<ol>
214+
<li><strong>衝突解決演練:</strong>建立一個模擬場景——main 上的 README.md 第 5 行改了,你的分支上同一行也改了。練習用 <code>git mergetool</code>(非編輯器手動解)解決衝突,比較兩種方式的效率。</li>
215+
<li><strong>分支策略選型:</strong>為一個「每兩週發版、同時修 hotfix」的團隊設計分支策略,畫出 Git 圖形並說明 release 與 hotfix 的合併路徑。</li>
216+
</ol>
217+
160218
</div>
161219
<footer>這是 GitLab 繁體中文教學站 · 由 OpenCode 建置<br>
162220
<span class="footer-license">本站教學內容(繁體中文解說)為本站原創,採 CC-BY-4.0;技術名詞與操作引用自 <a href="https://docs.gitlab.com/" rel="noopener">GitLab Docs</a><a href="https://git-scm.com/doc" rel="noopener">Git 官方文件</a></span></footer>

0 commit comments

Comments
 (0)