【Treeman】Git相關

【GitLab】相關

【GitLab】相關

【GitLab】gitlab-runner 執行環境種類

下面整理成表格給你(主流可用的 executor):

Executor 運作方式 優點 缺點 適用情境 設定/註冊要點
shell 直接在 Runner 主機的 shell 執行(bash / PowerShell) 最快、零容器開銷;可直接用主機已安裝工具 隔離最弱、容易「弄髒」主機;多專案易衝突 單機/內網、快速 smoke test、固定工具鏈 gitlab-runner register --executor shell;確保 gitlab-runner 使用者權限(如加入 docker 群組)與 builds_dir 可寫
docker 每個 job 以容器執行;image: 可指定環境 環境可重現、隔離佳、跨專案穩定 需管理映像;使用 Docker 需選擇掛 docker.sock 或 DinD 大多數 CI/CD 場景(前後端 build、容器化) --executor docker --docker-image <base>;若 job 需 docker build:① 掛 /var/run/docker.sock,或 ② DinD:privileged=true + services: docker:dind
kubernetes 每個 job 建一個 Pod 來跑 彈性擴縮、資源/隔離/配額完善 需 K8s 叢集與維運成本 中大型團隊、尖峰負載、雲原生 --executor kubernetes;於 config.toml 設 namespace、serviceAccount、pull secrets 等
ssh Runner 透過 SSH 登入遠端主機執行 可用現成遠端環境、無需在目標機器裝 Runner 隔離弱、擴展性差、權限管控要嚴格 特定機器/設備、臨時需求 --executor ssh;於 config.toml 填 host/user/key、路徑與環境
custom 以自訂腳本(prepare/run/cleanup)對接任意執行環境 彈性最高、可接非官方平台 需自寫與維護整套腳本,診斷較複雜 特殊平台、內部排程器 --executor custom;提供自訂 hook 腳本並測好錯誤處理
【GitLab】相關

【GitLab】升級相關

升級路徑
https://gitlab-com.gitlab.io/support/toolbox/upgrade-path/

【GitLab】相關

【GitLab】runner 使用 k8s 流程說明

 

一、前置條件


二、建立命名空間

kubectl create namespace gitlab-runner     # 放 Runner 本體
kubectl create namespace ci-jobs           # job 跑的位置(也可與上面同一 ns)

三、用 Helm 裝 Runner(K8s executor)

  1. 加入 chart

helm repo add gitlab https://charts.gitlab.io
helm repo update
  1. 建一份 values.yaml

gitlabUrl: "http://10.2.11.139/"
# 新流程建議用 runnerToken(glrt-...)
runnerToken: "glrt-xxxxxxxxxxxxxxxxxxxxxxxxxxxx"

rbac:
  create: true

serviceAccount:
  create: true
  name: gitlab-runner

runners:
  executor: kubernetes
  # job 要跑在哪個 ns;不填則跟 Runner 同 ns
  namespace: ci-jobs
  # 預設 job 容器用什麼 image(可被 .gitlab-ci.yml 的 image 覆蓋)
  image: alpine:3.20
  pollTimeout: 180

  # 是否允許特權容器(多數情況不需要,建議先關)
  privileged: false

  # 幫 job Pod 加上標籤(可選)
  podLabels:
    app: gitlab-ci-job

  # 預設資源限制(可選)
  resources:
    limits:
      cpu: "1"
      memory: "1Gi"
    requests:
      cpu: "200m"
      memory: "256Mi"

  # Cache(可選:接 S3/MinIO;此段示意,若未啟用請刪除)
  cache:
    type: s3
    path: "gitlab-runner"
    s3ServerAddress: "minio.minio.svc.cluster.local:9000"
    s3BucketName: "gitlab-ci-cache"
    s3AccessKey: "minio-access"
    s3SecretKey: "minio-secret"
    s3Secure: false

新流程下:tags / run-untagged / locked 等屬性建議在 GitLab UI 的 Runner 設定頁調整,不再用 CLI 參數寫入。

  1. 安裝

helm upgrade --install gitlab-runner gitlab/gitlab-runner \
  -n gitlab-runner -f values.yaml
  1. 驗證

kubectl -n gitlab-runner get pods
# 應看到 gitlab-runner 的 Pod(或 deployment/rs)

四、最小 .gitlab-ci.yml(驗證 K8s executor 正常)

stages: [ping]

hello:
  stage: ping
  image: alpine:3.20
  script:
    - echo "Runner: $CI_RUNNER_DESCRIPTION"
    - echo "Executor: Kubernetes OK"
    - cat /etc/os-release

跑起來時的 log 開頭應出現:Preparing the "kubernetes" executor
K8s 裡 ci-jobs 命名空間會看到對應的 Pod(生命周期:Running → Succeeded)。


五、在 K8s executor 內建 Docker 映像(推薦用 Kaniko)

K8s executor 不建議 DinD。常見做法是用 Kaniko(rootless,無需 Docker daemon)。

  1. 在 GitLab 專案 CI Variables 設定:

  1. Kaniko Job 範例

stages: [build]

docker-build:
  stage: build
  image:
    name: gcr.io/kaniko-project/executor:latest
    entrypoint: [""]
  variables:
    # registry 登入(若用 GitLab Container Registry,可改為 CI 提供的 token)
    DOCKER_CONFIG: /kaniko/.docker
  script:
    - >
      mkdir -p /kaniko/.docker &&
      cat > /kaniko/.docker/config.json <<EOF
      {
        "auths": {
          "${CI_REGISTRY}": {
            "auth": "$(printf "%s:%s" "$CI_REGISTRY_USER" "$CI_REGISTRY_PASSWORD" | base64 -w0)"
          }
        }
      }
      EOF
    - echo -e 'FROM alpine:3.20\nCMD ["echo","kaniko build OK"]' > Dockerfile
    - >
      /kaniko/executor
      --context "${CI_PROJECT_DIR}"
      --dockerfile "${CI_PROJECT_DIR}/Dockerfile"
      --destination "${CI_REGISTRY_IMAGE}:$CI_COMMIT_SHA"
      --destination "${CI_REGISTRY_IMAGE}:latest"

這個 job 會在 K8s 中跑 Kaniko,把映像打好推到 Registry,不需要 Docker daemon、也不需要 privileged。


六、(可選)Sidecar 服務示例(K8s 會幫你生多容器 Pod)

stages: [test]

pg-test:
  stage: test
  image: postgres:16-alpine
  services:
    - name: postgres:16-alpine
      alias: db
  variables:
    POSTGRES_PASSWORD: secret
  script:
    - psql -h db -U postgres -c "SELECT version();"

在 K8s executor 下,services: 會轉成 同一個 Pod 的 sidecar 容器,網路互通用 alias 連線。


七、常見疑難排解


八、如果不用 Helm(純手工方式,了解即可)

但維運上 Helm chart 會簡單很多(升級/回滾/佈署差異)。


需要我幫你把 values.yaml 客製到你的環境(例如 MinIO 位址、特定節點選擇器、Pod 安全性設定、預設資源)嗎?我可以直接產一份可用的版本給你。

【GitLab】相關

【GitLab】CI/CD Settings 說明

✅  General pipelines

image-1755143476227.png


1. Public pipelines 


2. Auto-cancel redundant pipelines 


3. Skip outdated deployment jobs 


4. Use separate caches for protected branches 


5. CI/CD configuration file


6. Git strategy


7. Git shallow clone


8. Timeout


我看你的設定,Git strategy 用 fetch + shallow clone 20,這樣拉程式會比較快,但如果你有需要依賴完整 commit 歷史(例如 git describe、全量 tag 檢出),要把 shallow clone 設成 0

✅ Pipeline status

image-1755161177902.png

這張圖是 GitLab 專案的 CI/CD 狀態徽章(Badges)設定頁,它提供了一些可以放到 README 或網頁上的「狀態顯示圖示」,用來即時反映專案的 CI/CD 情況。

分三塊說明:


1. Pipeline status(流水線狀態)


2. Coverage report(測試覆蓋率)


3. Latest release(最新版本)


4. 使用方式


✅ Auto DevOps

image-1755163898687.png

你這張圖是 GitLab Auto DevOps 的設定頁面,它是 GitLab 提供的一套「自動化 CI/CD Pipeline」功能,讓專案在沒有自訂 .gitlab-ci.yml 的情況下,也能自動完成建置、測試、部署等流程。


1. Default to Auto DevOps pipeline


2. 提示訊息

Add a Kubernetes cluster integration with a domain, or create an AUTO_DEVOPS_PLATFORM_TARGET CI variable.

3. Deployment strategy(部署策略)

三種選項:

  1. Continuous deployment to production(持續部署到正式環境)

    • 每次 Pipeline 成功就會自動部署到 Production。

  2. Continuous deployment to production using timed incremental rollout(定時漸進式部署)

    • 部署會分批釋出,逐漸更新所有節點(需要 Kubernetes 支援)。

  3. Automatic deployment to staging, manual deployment to production(自動部署到測試環境,手動部署到正式環境)

    • 先自動部署到 Staging 環境,Production 需要手動觸發。


4. 總結影響


✅ Runners

image-1755165012676.png

 


1. Runners 概念


2. Specific runners

這個區塊是專屬於當前專案的 Runner。
圖片中有兩個 active 的 Runner:

Runner 名稱 類型 Tag 狀態
#347 (UgMp--WG) Docker Executor app-docker-204 🟢 active
#343 (Mw1g8wwh) Shell/VM Executor app-docker-vm-204 🟢 active

Tag 作用:


3. Runner 註冊方式

左邊「Set up a specific runner for a project」提供:


4. Shared runners


5. Group runners


6. 運作重點


✅ Artifacts

Uploaded image

這張圖是 GitLab 專案的 Artifact 保留設定



使用情境


 

這張圖是 GitLab CI/CD 專案層級的 Variables 設定頁面,主要是用來存放敏感資訊(例如密碼、金鑰、帳號等),在 Pipeline 中可以直接引用。


Variables(變數)

1. Variables(變數)


2. 欄位說明

欄位 說明
Type 一般都是 Variable,也可能是 File(將值存成檔案再提供給 Job)。
Key 變數名稱(例如 PassWdUserName),在 CI/CD job 中用 $PassWd 存取。
Value 變數值(已隱藏),只有有權限的使用者才能看到。
Protected ✅ 表示這個變數只會在 Protected branchProtected tag 的 pipeline 中被注入。
Masked ✅ 代表在 Job log 中會以 ***** 隱藏,防止外洩(必須符合 GitLab Mask 規則)。
Environments 變數適用的環境,例如 Allproductionstaging 等。

3. 圖中範例


4. 使用範例

假設你在 .gitlab-ci.yml 中要用這兩個變數:

stages:
  - test

show-vars:
  stage: test
  script:
    - echo "User: $UserName"
    - echo "Password: $PassWd"

GitLab 裡,

Protected branch(受保護分支) 和 Protected tag(受保護標籤)
是用來防止重要分支或標籤被隨意修改、刪除、或由沒有權限的人 push 的安全機制。


Protected branch(受保護分支) 和 Protected tag (受保護標籤)

1. Protected branch(受保護分支)

主要特點:

範例情境


2. Protected tag(受保護標籤)

主要特點:

範例情境


3. 為什麼與 CI/CD Variables 有關

當你在 GitLab CI/CD 中將變數設定為 Protected = ✅ 時:

舉例

deploy:
  stage: deploy
  script:
    - echo $PROD_API_KEY

這是 Protected Branch / Tag 與 CI/CD 變數注入邏輯對照表

Pipeline 觸發來源 變數 Protected 設定 變數是否注入 說明
Protected branch(例如 master ✅ Protected ✅ 注入 變數只對受保護分支生效,符合條件可使用
非 Protected branch(例如 feature/test ✅ Protected ❌ 不注入 變數不會被注入,避免敏感資料外洩
Protected tag(例如 v1.0.0 ✅ Protected ✅ 注入 變數會注入到受保護標籤的 Pipeline
非 Protected tag(例如 test-1 ✅ Protected ❌ 不注入 變數不會被注入
任意 branch/tag ❌ 未 Protected ✅ 注入 不受限制,所有 Pipeline 都能用變數

💡 建議用法


✅ Pipeline triggers

image-1755166426157.png

你這張圖是 GitLab Pipeline Trigger 設定頁面,它的用途是建立一組 Trigger Token,讓外部系統或腳本可以直接觸發專案的 CI/CD Pipeline,而不用透過 Git push 或 Merge Request。


1. Trigger Token


2. 觸發方式

(1) 用 cURL

curl -X POST --fail \
  -F token=YOUR_TOKEN \
  -F ref=分支或tag名稱 \
  http://10.10.10.10/api/v4/projects/2406/trigger/pipeline

(2) 在 .gitlab-ci.yml 裡呼叫

script:
  - "curl -X POST --fail -F token=YOUR_TOKEN -F ref=master http://10.10.10.10/api/v4/projects/2406/trigger/pipeline"

(3) 用 Webhook 直接 GET

http://10.10.10.10/api/v4/projects/2406/ref/master/trigger/pipeline?token=YOUR_TOKEN

3. 傳入 Pipeline 變數

可以讓外部觸發時同時傳遞變數:

curl -X POST --fail \
  -F token=YOUR_TOKEN \
  -F ref=master \
  -F "variables[RUN_NIGHTLY_BUILD]=true" \
  http://10.10.10.10/api/v4/projects/2406/trigger/pipeline

4. 使用場景


💡 建議:


✅ Deploy freezes(部署凍結)

image-1755166820184.png

你這張圖是 GitLab 的 Deploy freezes(部署凍結)設定頁面,用來在特定時間區間禁止部署,避免在敏感時段(例如假日、系統維護時間、尖峰時段)誤發佈程式。


圖中設定解讀


功能運作方式

  1. 這裡的時間範圍只是定義凍結時段

  2. 要生效,必須在 .gitlab-ci.yml 的部署 job 中加上:

    deploy_job:
      stage: deploy
      script:
        - echo "Deploying..."
      rules:
        - if: $CI_DEPLOY_FREEZE == "true"
          when: never
        - when: on_success
    

    或使用 GitLab 內建的 deploy_freeze 規則

  3. 凍結期間,對應的部署 job 會直接跳過,不會觸發。


使用場景


✅ Token Access

image-1755167118948.png

這是 GitLab 專案設定裡的 Token Access(CI_JOB_TOKEN 存取控制) 功能,主要用來限制 CI/CD 任務中 CI_JOB_TOKEN 變數可以存取的其他專案,避免被濫用。



用途

  1. 跨專案存取 API
    在 CI/CD pipeline 中,可能需要用 curlwget 呼叫其他 GitLab 專案的 API,例如下載 artifact、觸發 pipeline。

  2. 限制安全風險
    如果沒有啟用限制,惡意程式碼可以利用 CI_JOB_TOKEN 存取同一 GitLab instance 中所有公開或有權限的專案

  3. 最佳實務

    • 如果專案需要 CI_JOB_TOKEN 存取別的專案 → 開啟並只加允許的專案。

    • 如果專案不需要跨專案存取 → 建議直接開啟限制並不加任何專案。


範例:跨專案下載 Artifact

假設專案 A 的 pipeline 要下載專案 B 的最新 build:

script:
  - curl --header "JOB-TOKEN: $CI_JOB_TOKEN" \
         "https://gitlab.example.com/api/v4/projects/123/jobs/artifacts/main/download?job=build" \
         -o artifact.zip

如果你啟用了限制,就必須在專案 B 裡把專案 A 加進「Projects that can be accessed」清單,否則會 403 Forbidden


 

 

【GitLab】相關

【GitLab】使用ssh clone 專案

以下是在 GitLab 使用 SSH 方式 clone 專案的完整步驟,假設你的 GitLab 伺服器是公司內部或自架的,也適用:


1️⃣ 產生並設定 SSH Key

  1. 建立 SSH Key

    ssh-keygen 
    
    • 出現檔案路徑提示時直接按 Enter (預設~/.ssh/id_rsa.pub)

    • 登入 GitLab → 右上角 使用者頭像PreferencesSSH Keys

    • 貼上 ~/.ssh/id_rsa.pub 內容。


2️⃣ 測試連線

確認 GitLab 可透過 SSH 連線:

ssh -T git@your.gitlab.host

3️⃣ 取得專案的 SSH URL

在 GitLab 專案頁面:


4️⃣ 執行 Clone

git clone git@gitlab.example.com:group-name/project-name.git

5️⃣ 常見問題排查

問題 檢查方式
Permission denied (publickey) 確認 ssh-agent 有加入金鑰:ssh-add -l
找不到 Host 檢查網路、防火牆,或在 ~/.ssh/config 加入 Host 設定
公司內網 GitLab 需確保內部 DNS 或 VPN 正確

範例 .ssh/config(可簡化命令)

Host gitlab-company
    HostName gitlab.example.com
    User git
    IdentityFile ~/.ssh/id_ed25519

然後可用:

git clone git@gitlab-company:group-name/project-name.git

以上步驟完成後,你就能用 SSH 方式安全地 git clone GitLab 專案並進行後續開發。

【GitHub】相關

【GitHub】相關

【Git】Github 新增專案檔案

create a new repository on the command line

echo "# sample_proj" >> README.md
git init
git add README.md
git commit -m "first commit"
git branch -M main
git remote add origin https://github.com/treemanou/sample_proj.git
git push -u origin main

 

push an existing repository from the command line

git remote add origin https://github.com/treemanou/sample_proj.git
git branch -M main
git push -u origin main

 

 

【GitHub】相關

【Git】解決github項目體積過大的問題

 

首先查找出大文件

$ git rev-list --objects --all | grep "$(git verify-pack -v .git/objects/pack/*.idx | sort -k 3 -n | tail -5 | awk '{print$1}')"


–objects:列出該提交涉及的所有文件ID。

–all:所有分支的提交,相當於指定了位於/refs下的所有引用。

verify-pack命令用於顯示已打包的內容,我們用它來找到那些大文件。

-v(verbose)參數是打印詳細信息。

前面我們通過rev-list得到了文件名-ID的對應關係,通過verify-pack得到了最大的5個文件ID。 用後者篩選前者便能得到最大的5個文件的文件名,比如:

$ git rev-list --objects --all | grep "$(git verify-pack -v .git/objects/pack/*.idx | sort -k 3 -n | tail -5 | awk '{print$1}')" b96695fd6e62fff41723ab324368da394f3a504e package-lock.json 76ec4d5d5fd79da922b322d53fbd1298dc128dd3 node_modules/acorn/dist/acorn.mjs.map 286dc92a240dac765d81dfbda451fd19f9611e84 node_modules/ajv/dist/ajv.bundle.js d2cc86eb230313af9bbdbd3faed7f8e7c7247788 node_modules/source-map-support/node_modules/source-map/dist/source-map.min.js.map aad0620d70e16717ec338fc1d332279739e0d97c node_modules/terser/node_modules/source-map/dist/source-map.debug.js

然後我們需要刪除他們

$ git filter-branch --force --prune-empty --index-filter 'git rm -rf --cached --ignore-unmatch YOU-FILE-NAME' --tag-name-filter cat -- --all

filter-branch命令可以用來重寫Git倉庫中的提交

–index-filter參數用來指定一條Bash命令,然後Git會檢出(checkout)所有的提交, 執行該命令,然後重新提交。

–all參數表示我們需要重寫所有分支(或引用)。

YOU-FILE-NAME 你查找出來的大文件名字

重複幾次,直到大文件全部刪除完畢。

如果你確定某一個文件夾下面都不是你需要的,那麼你可以直接刪除整個文件夾,比如:

$ git filter-branch --force --prune-empty --index-filter 'git rm -rf --cached --ignore-unmatch node_modules' --tag-name-filter cat -- --all

完成後,以強制覆蓋的方式推送你的repo, 命令如下:

$ git push --force --all

最後,雖然上面我們已經刪除了文件, 但是我們的repo裡面仍然保留了這些objects, 等待垃圾回收(GC), 所以我們要用命令徹底清除它, 並收回空間,命令如下:

$ rm -rf .git/refs/original/ 
$ git reflog expire --expire=now --all 
$ git gc --prune=now 

Enumerating objects: 116, done. 
Counting objects: 100% (116/116), done. 
Delta compression using up to 4 threads Compressing objects: 100% (53/53), done. Writing objects: 100% (116/116), done. 
Total 116 (delta 55), reused 116 (delta 55)

 

 

 

【Git】語法觀念

【Git】語法觀念

【Git】相關連結

github 線上教學
GitHub Learning Lab

Git基本原理介绍 | Escape (escapelife.site)

Learn Git Branching (gitee.io)

Git基本原理介绍 | Escape (escapelife.site)

【Git】語法觀念

【Git】還原相關

以下是關於 Git 還原(恢復)功能的完整說明

Git 還原功能總表

指令 還原範圍 是否會刪除暫存區 是否會刪除未追蹤檔案 適用情境
git checkout . 工作目錄 還原已追蹤檔案
git restore . 工作目錄 推薦用法,等同於 checkout .
git restore --staged 暫存區 還原 git add 的檔案
git reset 暫存區 退回 staging 區
git reset --hard HEAD 工作目錄 + 暫存區 是(若搭配 clean) 徹底放棄所有變更(⚠危險)
git clean -fd 未追蹤檔案/資料夾 無關 清空未納入 Git 管控的檔案
git revert <commit> 版本歷史 無關 安全回復 commit(保留紀錄)

 


Git 還原功能完整整理與使用說明

在日常開發中,Git 提供多種指令用來還原工作目錄、暫存區,或是回復錯誤的 commit。根據不同的需求,選擇合適的還原方式可避免資料遺失或版本混亂。


1. git checkout .

還原所有「已追蹤檔案」回到最新 commit 的狀態。

適用情境:


2. git restore(推薦用法)

git restore 是 Git 2.23+ 提供的新指令,取代過去 checkout 的混用狀況。

範例:

git restore .                # 還原所有檔案
git restore path/to/file.js # 還原單一檔案

3. git restore --staged

還原暫存區的內容,讓已 git add 的檔案退回至工作目錄狀態。

git restore --staged path/to/file.js

4. git reset

還原 staging 區(暫存區),讓所有已 git add 的檔案回到修改中狀態。

git reset

5. git reset --hard HEAD

工作目錄與暫存區 都還原成最近一次提交(HEAD)的狀態。

git reset --hard HEAD

適用情境:


6. git clean -fd

清除所有「未被追蹤的檔案與資料夾」。

git clean -fd

適用情境:


7. git revert

對某個已提交的 commit 產生一個「反向操作的 commit」。

git revert <commit_hash>

適用情境:


 

【Git】語法觀念

【Git】TorotoiseGit 占用資源解決方法

 

image-1637655094637.png

【原因】 TorotoiseGit 會掃描硬碟內有git 版控資料夾的的異動,並產生相對應的圖示,有時會造成主機磁碟讀寫過高

image-1615526155670.png

【解決】限縮掃描範圍

任一個資料夾按右鍵->【TortoiseGit】->【setting】

image-1637655137735.png

image-1637655158072.png

Exclude paths: 將本機的每一個磁碟加入

Include paths: 將有用到git的目錄加入

【Git】語法觀念

【Git】windows系統 warning: LF will be replaced by CRLF in

windows系統下使用git出現:warning: LF will be replaced by CRLF in

$ git add readme.txt readme.txt
warning: LF will be replaced by CRLF in learngit/readme.txt.
The file will have its original line endings in your working directory

原因是windows系統的換行符和Unix下的換行符不同,但是git會幫我們自動進行換行符的轉換,所以出現了這個warning


# 解決的方法就是,禁止自動轉換:
$git config –-global core.autocrlf false

https://noelhsiao.medium.com/%E9%81%87%E5%88%B0-warning-lf-will-be-replaced-by-crlf-in-%E8%A9%B2%E6%80%8E%E9%BA%BC%E8%A7%A3-ab9882ee07be

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

【Git】語法觀念

【Git】checkout 與 switch 比較

我來幫你整理 git switchgit checkout 的差異,並用表格讓你快速比較。


1️⃣ 歷史背景


2️⃣ 功能比較表

功能 git checkout git switch
切換到已存在分支 git checkout branch_name git switch branch_name
建立並切換到新分支 git checkout -b new_branch git switch -c new_branch
檢出特定 commit / tag git checkout commit_hash ❌ 不支援
檢出特定檔案版本 git checkout commit_hash -- file.txt ❌ 不支援
語意單純性 ❌ 功能太多易混淆 ✅ 專注於切換分支
推薦使用情境 老專案 / 習慣舊指令 新專案 / 想簡化操作

3️⃣ 使用範例

切換到現有分支

# 傳統方式
git checkout dev

# 新方式(推薦)
git switch dev

建立並切換到新分支

# 傳統方式
git checkout -b feature/login
# 新方式(推薦)
git switch -c feature/login

4️⃣ 為什麼官方推薦 git switch


💡 簡單記


太好了!以下是 git switchgit restore 如何取代舊指令 git checkout完整對照表,讓你更容易理解並開始使用新指令:


git checkout 對照表:對應的新指令用法

原本 git checkout 用法 對應的新指令 功能說明
git checkout <branch> git switch <branch> 切換到已存在的分支
git checkout -b <new-branch> git switch -c <new-branch> 建立並切換到新分支
git checkout <commit> ❌(建議保留 checkout 切換到某個 commit 狀態(暫不取代)
git checkout <file> git restore <file> 還原工作區中的單一檔案
git checkout -- <file> git restore <file> 同上
git checkout <commit> -- <file> git restore --source <commit> <file> 還原某個 commit 中的檔案
git checkout . git restore . 還原所有工作區的檔案
git checkout HEAD <file> git restore --source=HEAD <file> 還原最新 commit 的某個檔案
git checkout HEAD^ ❌(建議保留 checkout 切換到上一個 commit(建議保留舊指令)

 

💡 建議做法

任務 建議用法
切換分支 git switch dev
建新分支並切過去 git switch -c feature/new-ui
還原單一檔案 git restore src/App.tsx
還原某 commit 的檔案 git restore --source=abc123 file.txt
還原整個工作目錄 git restore .

🚀 Git 版本要求


 

【Git】語法觀念

【Git】HEAD 是什麼

當然可以!HEAD 是 Git 中最核心也是最常見的概念之一,很多 Git 指令(如 resetcheckoutrebase)都與它有關。下面我會從簡單到深入,幫你完整說明:


一句話理解 HEAD 是什麼:

HEAD 是你目前所在的分支的「指標」,也就是「你現在工作的 commit」位置。


基本概念圖:

假設你有三個 commit:

A → B → C
        ↑
      HEAD
A → B → C → D
              ↑
            HEAD

 

 HEAD 的 3 種狀態:

狀態類型 說明
HEAD → 分支名稱(正常狀態) 你在某個分支上(例如 maindev
HEAD → commit(detached) 你處於「分離 HEAD 狀態」(Detached HEAD)
HEAD → 其他指標 比如在 Rebase、Merge 中會指向暫存區域

✅ 常見用途說明

1. HEAD 是你目前的開發位置

當你執行:

git commit

其實 Git 是「把你的 commit 接在 HEAD 指向的 commit 後面」。


2. HEAD 是 Git 重設的基準點

git reset --hard HEAD

這表示:把你的暫存區與工作目錄都還原成目前這個 commit 的狀態。


3. HEAD^HEAD~1:往上移動一個 commit

表示法 意思
HEAD 現在這個 commit
HEAD^ 上一個 commit(parent)
HEAD~1 HEAD^
HEAD~2 往上兩個 commit

🚨 Detached HEAD(分離 HEAD 狀態)

當你執行:

git checkout <某個 commit 哈希>

你會進入「Detached HEAD」狀態:

A → B → C
        ↑
     (HEAD)

你不再是在某個分支上,而是「直接指向某個 commit」。這時如果你做出 commit,它們會變成「懸空」,容易被 Git 回收(垃圾回收)。

所以如果你看到這樣的訊息:

You are in 'detached HEAD' state.

請小心:最好先建立分支來保存變更:

git checkout -b temp-branch

🧭 總結:HEAD 是 Git 的當前位置指標

功能 用途說明
表示目前 commit 所有操作(commit、reset)都以它為基礎
指向當前分支 預設情況 HEAD 是指向你當前分支
變更分支 = 移動 HEAD 切分支就是改變 HEAD 的位置
可用於版本回朔、還原 HEAD^HEAD~2 常見於 reset、diff 等
被分離 = Detached HEAD 指向 commit 而非分支,要小心變更遺失

如果你想要我畫一張圖示 HEAD 與分支移動的流程圖,也可以說一聲,我能幫你生成視覺化版本!是否需要?


為什麼我們要「移動 HEAD」?

簡單來說:

移動 HEAD = 改變我們正在「看的版本」、「工作的版本」、或「建立新歷史的起點」。

Git 是一個版本控制系統,HEAD 就像「目前播放的時間軸指標」,移動它可以讓你做版本切換、回朔、修正、實驗開發等動作。


✅ 移動 HEAD 的常見目的(整理成表)

用途/目的 說明
🔄 切換分支或版本 改變目前正在編輯/開發的版本,比如 git switch dev(切換 HEAD 到 dev)
🧭 回朔 commit 想把 HEAD 拉回到前一版:git reset --hard HEAD^
🧪 版本測試或除錯某一版 git checkout <commit> 移動到某個版本試驗、測試(會進入 detached HEAD)
🧹 清除或重建 commit 歷史 git resetrebase 改變 HEAD 來整理版本歷史
🧱 建立新的分支開發點 移動 HEAD 到 commit 後再用 git switch -c new-branch 開分支
🔥 放棄變更並回到穩定版本 移動 HEAD 到穩定 commit 位置,還原所有內容

 舉幾個具體例子


1️⃣ 切換分支(背後其實是移動 HEAD)

git switch dev

📌 HEAD 從 main → dev,代表你現在工作的是 dev 的最新 commit。


2️⃣ 回到前一版(移動 HEAD 到上一個 commit)

git reset --hard HEAD^

📌 HEAD 往回一格,捨棄最近一次的提交內容(危險但有用)。


3️⃣ 想測試舊版功能(Detached HEAD 狀態)

git checkout abc1234

📌 HEAD 不再指向分支,而是指向一個 commit,你進入「Detached HEAD」狀態,可以安全看舊版本。


4️⃣ 切 HEAD + 建立新分支(從中間版本開新分支)

git checkout abc1234
git switch -c fix-login

📌 移動 HEAD 到舊版,再基於此版本開新分支,進行 hotfix。


 把 HEAD 當「播放頭」的比喻

想像 Git 是個影片編輯器:

這樣你就能理解:


✅ 小結:為什麼要移動 HEAD?

目的 解釋
🧭 切換你正在工作的版本 因為 HEAD 代表你「現在的位置」
🔙 回到過去版本 移動 HEAD 讓你回到某個穩定 commit
🧪 實驗新東西 / 修 bug 從舊 commit 移動 HEAD,開新分支來做測試與修復
🔧 重構 Git 歷史 通過 reset 或 rebase 移動 HEAD 重寫 commit 歷史

這是個很關鍵的 Git 概念問題!
當你的 HEAD 不在任何分支上,而是直接指向某個 commit,這個狀態稱為:


⚠️ Detached HEAD(分離 HEAD 狀態)


✅ 什麼是 Detached HEAD?

正常情況:

HEAD → main → C

Detached HEAD 狀況:

HEAD → C  (但不是任何分支)

你直接「跳到一個 commit」,例如透過:

git checkout abc1234

或:

git switch --detach abc1234

這時你就脫離了任何分支的控制,你在 那個 commit 上自由工作,但:

🧨 所做的一切(如新增 commit)都不屬於任何分支,如果不小心離開就會「失聯」。


Detached HEAD有什麼影響?

有什麼影響?

結果 說明
✅ 可以修改檔案、做 commit 你仍然可以正常工作(只是沒有在分支上)
🧨 新的 commit 沒有分支指向 所有新 commit 是「懸空狀態」,不儲存在任何分支上
🧹 一旦切換到其他分支就可能遺失那些 commit 除非你把它們另存(例如建立新分支),否則 Git 垃圾回收後就找不回來
🧠 git status 會提示 Detached HEAD 告訴你現在是在 Detached 狀態

什麼情況會進入 Detached HEAD?

情境 指令
想要看舊版本 git checkout <commit-hash>
從某個 commit 測試 / 編譯 git switch --detach <commit>
在 CI/CD 工具中 checkout 特定 commit 例如 GitHub Actions 的 actions/checkout@v2 預設為 Detached
你用 git reset --hard 到某個 commit HEAD 也會臨時分離

✅ 正確處理方式:建立分支保存你做的事!

如果你在 Detached HEAD 狀態下做了 commit,請馬上建立一個分支把它們保存下來:

git switch -c fix-login-bug

這樣你的 commit 就有名字,不會被回收。


 總結:Detached HEAD 是可用但有風險的模式

特性 狀態說明
可以編輯與 commit ✅ 是
commit 是否屬於分支 ❌ 否
離開當前 commit 後是否會遺失 ✅ 會(除非建立分支)
建議 要保留修改就馬上建立分支

 

【Git】語法觀念

【Git】每個 commit 不都是從某個分支出來的嗎?

這是個非常棒的深入問題,顯示你對 Git 的理解已經進入「底層思維模式」,我們來一一說明:


一句話解釋你提的問題:

不是每個 commit 都屬於分支,但每個分支都指向某個 commit。

這句話是 Git 的核心設計邏輯,反直覺但重要。


 先理解 Git 的本質:commit 是資料庫,分支是指標

在 Git 裡:

✅ 當你做 commit 時發生了什麼?

  1. Git 會建立一個新 commit(有一個父 commit)

  2. HEAD 所在的分支(如 main)會更新,指向這個新的 commit

所以我們通常覺得 commit 是從分支「出來」的,但其實:

🔍 分支並不綁定在 commit 上,是 commit 被分支「指到了」。


❗Detached HEAD:從 commit 建立 commit,但不屬於分支

來看個例子:

git checkout abc1234   # 進入 detached HEAD
echo "foo" > a.txt
git add a.txt
git commit -m "detached commit"

這時你新增的 commit 並不屬於任何分支!

A --- B --- C    ← main
           \
            D   ← HEAD (沒有分支名稱指向)

如果你切走:

git switch main

那個 D commit 就被遺棄了,未來可能被 Git 垃圾回收(GC)清掉。


分支只是「指到某個 commit」的名稱

你可以用 git branch 動態為任何 commit 建立分支:

git branch recover-commit abc1234

這個 abc1234 本來不是任何分支,但現在你「取了個名字」給它,它就變成你認為的「分支」。


實際演示:證明 commit 不一定屬於分支

git init
echo "init" > a.txt
git add .
git commit -m "init commit"
git checkout HEAD^ --detach
echo "detached" > a.txt
git commit -am "detached commit"
git log --oneline --decorate

你會看到第二個 commit 沒有任何分支名稱指向它,只是個孤兒 commit。


所以回到你的問題:

❓「每個 commit 不都是從某個分支出來的嗎?」

🔸 表面上是,但實際上:

就像硬碟上的檔案可以沒被任何資料夾引用一樣,但它依然存在(直到被清理)


 類比理解

Git 概念 類比成電腦系統
commit 實際的檔案內容(在磁碟上)
分支(branch) 檔案捷徑(shortcut)
HEAD 你正在開啟的那個捷徑
detached HEAD 你直接打開某個檔案(沒從捷徑)

 

【Git】語法觀念

【Git】head, tag, commit, branch的關係

這是一個非常關鍵的 Git 理解核心:
HEADtagcommitbranch 彼此的關係
我幫你用「定義 + 關聯圖 + 對照表 + 比喻」完整整理如下:


✅ 一張圖:理解 Git 中 HEAD、分支、Tag、Commit 的關係

          HEAD
            ↓
        ┌────────┐
        │ branch │──┐
        └────────┘  │
                    ↓
         ┌────────────────┐
         │     commit     │◄──┐
         └────────────────┘   │
                  ▲          │
        ┌─────────┴──────┐   │
        │     another     │  │
        │     branch      │  │
        └─────────────────┘  │
                             │
                        ┌─────────┐
                        │  tag    │──► 同樣也指向 commit
                        └─────────┘

🧠 核心定義

名稱 定義說明
commit Git 的基本單位,是一個「版本快照」,有父子連結,不會變動
branch 指向某個 commit 的「可移動指標」,像捷徑,可以新增、移動
HEAD 代表你目前工作的「游標」,通常指向一個分支(或直接指向 commit)
tag 指向某個 commit 的「不可變名稱」(常用來標記版本,如 v1.0.0

🔗 它們的關係總結

關係 說明
branchcommit 分支就是指向某個 commit 的「指標」
HEADbranch or commit HEAD 是你「目前所在的位置」,可以指向分支或直接指向 commit(detached HEAD)
tagcommit Tag 永遠指向某個 commit,是不可變的
commit 之間 commit 是鏈狀連結(每個有一個 parent commit)

📁 類比說明(像檔案系統)

Git 概念 類比 說明
commit 檔案版本 是實際的內容快照(不可變)
branch 資料夾捷徑 可以移動、可以新建、可以切換
HEAD 滑鼠游標 你目前的編輯焦點(在哪個捷徑/檔案上)
tag 唯一標籤貼紙 永久貼在某個版本上,表示這是一個重要的版本點

📌 補充:變動性比較

元件 是否可變動 常見操作
commit ❌ 不可變 一旦建立就不會改變
branch ✅ 可變動 可以移動、刪除、重新建立
tag ✅ 可刪除(內容不可變) 可以刪除再重建,但本身是不可移動的指標
HEAD ✅ 一直在動 跟著你切換分支、commit 而變動

✅ 常見操作對應關係

操作說明 HEAD 變動 branch 變動 commit 變動 tag 變動
git switch dev
git commit ✅(會跟著 HEAD 一起動) ✅(新增)
git reset --hard HEAD^ ✅(可能丟失)
git tag v1.0
git checkout <commit> ✅(分離)
git switch -c new-feature ✅(新建)

✅ 總結一句話:


 

【Git】語法觀念

【Git】git revert <commit> 和 git checkout <commit> 差異

git revert <commit>git checkout <commit> 雖然都能「回到某個 commit」,但本質上用途完全不同。以下為詳細說明與比較。


一、git revert <commit>

功能說明:

特性:

使用情境:

範例:

git revert a1b2c3d

會產生一個新的 commit,把 a1b2c3d 的內容還原。


二、git checkout <commit>(或 git switch --detach <commit>

功能說明:

特性:

使用情境:

範例:

git checkout a1b2c3d
# 或推薦用法(Git 2.23+)
git switch --detach a1b2c3d

三、兩者比較表

指令 動作類型 是否建立新 commit 是否修改歷史 是否可安全推送遠端 常見用途
git revert <commit> 建立反向 commit ✅ 是 ❌ 否 ✅ 是 撤銷已推送的錯誤 commit
git checkout <commit> 切換版本 ❌ 否 ❌ 否 ⚠️ 不適合推送 detached commit 查看歷史、測試、debug

四、補充說明:若想基於某個舊 commit 建立新分支

git checkout -b new-branch a1b2c3d

這樣可以保留該版本的狀態,並在其上繼續開發,而不會讓 HEAD 處於 detached 狀態。


如果你有實際情境(例如:某個 commit 上錯 production,或想回復某功能),可以提供情況,我能幫你判斷該用 revert 還是 checkout 或其他方案。

【Git】語法觀念

【Git】常用指令

 

Git 進階指令速查表(實戰版)

類別 指令 說明 常見情境
Merge git merge branch 合併 branch feature 合併到 main
Rebase git rebase branch 重排 commit 整理 commit 歷史
Rebase git rebase -i HEAD~3 互動式 rebase squash commit
Cherry-pick git cherry-pick <commit> 套用指定 commit hotfix
Revert git revert <commit> 回復某 commit 線上 rollback
Reflog git reflog 查看 HEAD 歷史 找回被 reset 的 commit

Rebase vs Merge

操作 指令 結果
merge git merge main 保留 merge commit
rebase git rebase main 重新排列 commit

Merge

A---B---C main
     \
      D---E feature
           \
            F (merge)

Rebase

A---B---C main
           \
            D'---E' feature

📌 結論

操作 使用情境
merge 保留歷史
rebase 整理 commit

Interactive Rebase(整理 commit)

git rebase -i HEAD~3

會出現

pick a1b2 commit1
pick c3d4 commit2
pick e5f6 commit3

可修改為

pick a1b2 commit1
squash c3d4 commit2
squash e5f6 commit3

結果:

commit1 + commit2 + commit3
變成一個 commit

常用於:

PR 整理 commit

Cherry-pick(套用某 commit)

git cherry-pick <commit-id>

用途:

情境 範例
hotfix 從 dev 複製到 main
patch 套用某 bug fix

例如:

dev
A--B--C--D

main
A--B
git cherry-pick D

結果

main
A--B--D

Revert(安全 rollback)

git revert <commit>

Git 會產生一個 反向 commit

例如:

A--B--C

revert B

A--B--C--D
        ↑
     undo B

📌 適合

production rollback

Reflog(救命指令)

查看 HEAD 歷史

git reflog

例如

a1b2 HEAD@{0}: reset: moving to HEAD~1
c3d4 HEAD@{1}: commit: fix bug

恢復:

git reset --hard c3d4

很多工程師不知道:

Git 幾乎不會真的丟資料
reflog 都能救回

Detached HEAD

發生情況

git checkout <commit-id>

Git 會顯示

You are in 'detached HEAD' state

代表:

HEAD 沒有 branch

解法

建立 branch:

git checkout -b new-branch

Clean(清除未追蹤檔案)

查看將刪除

git clean -n

刪除

git clean -fd

常用於:

CI pipeline
重新 build

Force Push

git push -f

⚠️ 危險

可能覆蓋他人 commit

安全方式:

git push --force-with-lease

這會檢查遠端是否被更新。


Reset / Restore / Checkout 差異

指令 影響範圍
reset commit + staging
restore working tree
checkout branch 或檔案

Git 三層結構(核心概念)

Git 有三個區域:

Working Directory
↓
Staging Area (Index)
↓
Repository (Commit)

對應指令:

操作 指令
working → staging git add
staging → repo git commit
repo → working git checkout
repo → staging git reset

DevOps 常用 Git 重置流程

很多 CI pipeline 會用:

git fetch origin
git reset --hard origin/main
git clean -fd

作用:

確保 workspace 乾淨

Git Flow(常見分支策略)

常見 branch:

main
develop
feature/*
hotfix/*
release/*

流程:

feature -> develop
develop -> release
release -> main
hotfix -> main

Git Debug 指令

指令 用途
git blame file 查看誰修改
git bisect 找 bug commit
git show 查看 commit
git diff commit1 commit2 比較 commit

工程師最強 Git 指令 TOP 10

指令 用途
git log --oneline --graph 查看歷史
git reflog 救 commit
git rebase -i 整理 commit
git cherry-pick 套 commit
git revert rollback
git clean -fd 清 workspace
git reset --hard 重置
git stash 暫存
git blame 找修改人
git bisect 找 bug

💡 給你一個小建議

如果你常用 Git(你目前 DevOps / CI / Jenkins workflow 看起來是這樣),
最推薦記住 這 6 個核心指令

git log --oneline --graph
git reflog
git rebase -i
git cherry-pick
git reset --hard
git clean -fd

這份會非常接近 資深工程師 Git 操作指南

【Git】茶包射手