定閱客戶

2025年7月20日 星期日

 

Git 檔案管理與版本控制問答(1)


1. 修改 Git 目錄中的檔案後,需要 git add 嗎?

是的,如果你修改了 Git 追蹤的檔案,你必須使用 git add <檔案名> 來將這些修改加入到暫存區 (staging area)

即使檔案已經在 Git 倉庫中,每次你對它進行修改後,Git 都會將這些修改視為「未暫存的變更」。git add 命令的作用就是告訴 Git 你準備將這些變更包含在下一次的提交 (commit) 中。

簡單來說,Git 工作流程是這樣的:

  1. 修改檔案: 你在工作目錄中對檔案進行編輯。

  2. 暫存變更: 使用 git add <檔案名> 將修改後的檔案加入暫存區。你也可以使用 git add . 來暫存所有未暫存的變更(包括新增、修改、刪除的檔案)。

  3. 提交變更: 使用 git commit -m "你的提交訊息" 將暫存區中的變更提交到本地倉庫。

如果你沒有 git add 就直接 git commit,Git 只會提交上次 git add 後的狀態,而你最新的修改將不會被包含在這次提交中。


2. 暫存區的概念是指在哪裡?

Git 的「暫存區 (Staging Area)」又稱為「索引 (Index)」,它是一個非常重要的概念,扮演著工作目錄 (Working Directory) 和 Git 倉庫 (Repository) 之間的一個中間層緩衝區

暫存區的概念

你可以把暫存區想像成一個準備區收貨區

  • 工作目錄:是你實際編輯檔案的地方,就像你的辦公桌,你可以在上面任意修改文件。

  • 暫存區 (Staging Area):就像是倉庫門口的一個小廣場。當你完成了部分修改,並決定將這些修改納入下一次提交時,你會使用 git add 命令將這些修改的檔案「搬到」這個小廣場上。

  • Git 倉庫 (Repository):就像是你的實際倉庫。當你覺得小廣場上收集的檔案已經足夠形成一個完整的「包裹」(也就是一個版本提交)時,你就會使用 git commit 命令,把小廣場上的所有檔案打包並存入倉庫,同時留下一個記錄。

暫存區的實際位置

在 Git 的底層,暫存區實際上是一個位於你的 Git 專案根目錄下的隱藏資料夾 .git 裡面的檔案,通常是 .git/index。這個 index 檔案會記錄:

  • 有哪些檔案將會被包含在下一次的提交中。

  • 這些檔案在暫存區中的「快照」資訊(例如檔案內容的哈希值、檔案模式等)。

為什麼需要暫存區?

Git 引入暫存區的設計有幾個主要的好處:

  1. 精確控制提交內容:你可以「挑選」哪些修改要包含在當前的提交中,實現原子性提交

  2. 隔離工作目錄與版本庫:提供一個隔離層,讓你可以在提交前對變更進行審查和確認。

  3. 預覽即將提交的內容:在提交之前,你可以使用 git status 查看暫存區裡有哪些變更準備提交(通常顯示為綠色),或使用 git diff --staged 查看具體內容差異。


3. git init 的目錄是什麼地方?

當你執行 git init 命令時,你所在的當前目錄就會被初始化為一個 Git 倉庫。

git init 命令會在當前目錄下建立一個名為 .git 的隱藏子目錄。這個 .git 目錄就是 Git 倉庫的核心,它包含了所有 Git 管理專案所需的檔案和資料。

舉例說明:

如果你在 /Users/yourname/Documents/my_project 這個目錄裡執行 git init,那麼這個 my_project 資料夾就會變成一個 Git 倉庫,Git 會在裡面建立一個 .git 資料夾。從此以後,你對 my_project 資料夾及其子資料夾中的檔案所做的任何更改,都可以透過 Git 來追蹤和版本控制。


4. 直接修改 git init 後的目錄檔案是正確的嗎?

你直接修改 git init 後的目錄裡的檔案是完全正確且正常的

這是 Git 的基本工作流程

當你執行 git init 之後,Git 就開始監控這個目錄。你的工作流程通常是:

  1. 直接修改檔案:你在這個目錄裡新增、編輯、刪除檔案。這就是你的 工作目錄 (Working Directory)

  2. git add 暫存:當你覺得某個檔案的修改完成,準備好要儲存這個版本時,才用 git add <檔案名> 把這些變更放到暫存區 (Staging Area)

  3. git commit 提交:然後再用 git commit 把暫存區裡的內容永久記錄到 Git 倉庫 (Repository) 中,形成一個新的版本。

Git 的設計理念就是讓你能在最自然的環境下工作,也就是直接在你的檔案系統中修改檔案。Git 會在幕後追蹤這些變更。


5. 如果修改的檔案想放棄,如何恢復之前的內容?

如果你在 Git 專案中修改了檔案,但想放棄這些修改,恢復到之前的內容,你需要根據檔案的狀態選擇不同的 Git 命令。

1. 檔案在工作目錄中被修改,但還沒有執行 git add

這是最常見的情況。

  • 放棄單一檔案的修改:

    git restore <檔案名>

    或 (舊版 Git 習慣用法):

    git checkout -- <檔案名>

    這個命令會將 <檔案名> 恢復到上次提交 (commit)上次暫存 (git add) 時的狀態。

  • 放棄所有已修改但未暫存的檔案:

    git restore .

    或:

    git checkout -- .

    這個命令會將你工作目錄中所有已追蹤且已修改但未暫存的檔案,恢復到上次提交或上次暫存的狀態。

2. 檔案在暫存區中 (已執行 git add)

  • 將檔案從暫存區「取消暫存」,但保留工作目錄的修改:

    git restore --staged <檔案名>

    這個命令會把檔案從暫存區中移除,但你對檔案的修改依然保留在工作目錄裡。

  • 同時放棄暫存區和工作目錄的修改: 如果你想一次性丟棄所有修改,可以先取消暫存,再放棄工作目錄的修改,或者使用:

    git reset --hard HEAD

    注意: git reset --hard HEAD 這個命令非常強大且危險!它會丟棄所有已暫存和未暫存的修改,讓你的工作目錄完全回到上一次提交的狀態。請務必確認你真的不需要這些修改,因為這些修改將無法恢復

3. 新增的檔案 (未被 Git 追蹤)

如果你建立了一個新檔案,但還沒有執行 git add,可以直接在檔案系統中手動刪除它。

如果你想一次性刪除所有未追蹤的檔案:

git clean -f

如果要連未追蹤的資料夾也一起刪除,加上 -d 參數:

git clean -fd

注意: git clean 也是一個破壞性命令,它會永久刪除所有未追蹤的檔案和資料夾,無法恢復,請務必小心使用!


6. 有辦法指定恢復到哪個版本嗎?

當然可以!Git 是為了版本控制而設計的,所以你可以非常精確地指定要恢復到哪個版本(也就是哪個 commit)。

要做到這一點,你需要先知道你想恢復到的那個版本的 Commit Hash(提交雜湊值)。

如何找到 Commit Hash

你可以使用 git log --oneline 命令來查看你的提交歷史,並找到你需要的 Commit Hash:

git log --oneline

恢復到指定版本的方法

根據你想要達到的「恢復」目的,有幾種不同的方法:

1. git checkout <commit-hash> (用於查看歷史版本)

這個命令會將你的工作目錄和索引(暫存區)設定為指定提交的狀態。

  • 優點: 快速查看專案在特定時間點的樣子。

  • 缺點: 會讓你進入「分離頭部 (detached HEAD)」狀態。在此狀態下直接進行新的提交,這些提交將不會屬於任何分支,容易「丟失」。

  • 用法: git checkout <commit-hash>

  • 離開「分離頭部」狀態: 回到你之前所在的分支:git switch -git checkout -;或從當前分離的提交建立一個新分支:git checkout -b <新分支名稱>

2. git reset --hard <commit-hash> (重置到指定版本,會丟失後續提交的修改,請謹慎使用!)

這個命令會將你的當前分支指向指定的提交,並丟棄該提交之後的所有提交和所有工作目錄中的變更

  • 優點: 如果你確定要完全抹去歷史中某個提交之後的所有東西,這個方法最直接。

  • 缺點: 非常危險! 它會永久性地刪除指定提交之後的所有歷史記錄和工作目錄中的未提交變更,無法恢復。切勿在已經推送到遠端且他人正在協作的分支上使用此命令

  • 用法: git reset --hard <commit-hash>

3. git revert <commit-hash> (建立一個新的提交來「撤銷」指定提交的變更,保留歷史,推薦使用)

這個命令不會刪除任何歷史提交。相反,它會建立一個新的提交,這個新提交的內容是撤銷了指定提交所引入的變更

  • 優點:

    • 安全: 不會修改或刪除任何現有的歷史提交,是「非破壞性」的。

    • 保持歷史: 提交歷史是完整的,你可以清晰地看到哪些變更被引入,又有哪些變更被撤銷了。

    • 適用於協作: 由於它不會重寫歷史,非常適合在已經推送到遠端倉庫的公共分支上使用。

  • 缺點: 如果要撤銷一系列提交,可能會產生很多 revert 提交,讓歷史看起來有點冗長。

  • 用法: git revert <commit-hash>

選擇哪種方法?

  • 想看舊版本,不打算在其上繼續開發: 使用 git checkout <commit-hash> (進入分離頭部狀態)。

  • 想完全抹除某些提交,只在本地且確定無後顧之憂: 使用 git reset --hard <commit-hash> (危險!)。

  • 想撤銷某個提交的影響,但保留完整的提交歷史,尤其是在協作環境中: 強烈推薦 git revert <commit-hash>

在執行任何重置或撤銷操作之前,建議你先用 git statusgit log 仔細檢查當前的狀態和歷史,並確認你想要達成的效果。

2025年7月16日 星期三

Git 快速教學:核心概念與常用指令

什麼是 Git?

Git 是一個版本控制系統,幫助你追蹤程式碼的變更、協作開發,並在需要時回溯到之前的版本。它廣泛應用於軟體開發。

事前準備

  1. 安裝 Git
  2. 下載並安裝 Git:https://git-scm.com/
  3. 確認安裝:在終端機輸入 git --version,檢查是否有版本號輸出。
  4. 設置基本資訊bash git config --global user.name "你的名字" git config --global user.email "你的電子郵件" 這會告訴 Git 你的身份,方便在提交時記錄。

Git 核心工作流程

1. 初始化與基本操作

  • 創建新倉庫bash git init 在當前資料夾初始化一個新的 Git 倉庫,會生成一個 .git 隱藏資料夾。
  • 檢查狀態bash git status 查看當前倉庫的狀態(哪些檔案被修改、待提交等)。
  • 添加檔案到暫存區bash git add 文件名 git add . # 添加所有變更的檔案
  • 提交變更bash git commit -m "提交訊息" 將暫存區的變更儲存到倉庫,提交訊息應簡潔描述變更內容。

2. 查看歷史與回溯

  • 查看提交歷史bash git log git log --oneline # 簡潔版顯示 查看所有的提交記錄,每個提交有唯一的 commit ID
  • 回溯到某個版本bash git checkout <commit-id> # 切換到特定提交 git checkout main # 回到主分支
  • 還原變更bash git restore 文件名 # 放棄未暫存的修改 git restore --staged 文件名 # 取消已暫存的檔案 git reset HEAD^ # 回退最後一次提交(保留變更)

3. 分支管理

分支是 Git 的強大功能,允許多人並行開發或嘗試新功能。

  • 創建分支bash git branch 分支名稱
  • 切換分支bash git checkout 分支名稱 git switch 分支名稱 # 較新指令
  • 創建並切換分支bash git checkout -b 分支名稱 git switch -c 分支名稱
  • 合併分支bash git checkout main # 先切換到目標分支 git merge 分支名稱 # 將指定分支合併到當前分支
  • 刪除分支bash git branch -d 分支名稱

4. 遠端倉庫操作

Git 通常與遠端倉庫(如 GitHub、GitLab)配合使用。

  • 連接到遠端倉庫bash git remote add origin <遠端倉庫 URL>
  • 推送本地變更到遠端bash git push origin 分支名稱
  • 拉取遠端變更bash git pull origin 分支名稱
  • 克隆遠端倉庫bash git clone <遠端倉庫 URL>

5. 解決衝突

當多人修改同一檔案時,可能發生合併衝突: 1. 執行 git mergegit pull 時,Git 會提示衝突。 2. 打開衝突檔案,手動修改標記為 <<<<<<<>>>>>>> 的部分。 3. 修改完成後,執行: bash git add 衝突檔案 git commit

實用技巧

  • 快速提交bash git commit -am "提交訊息" # 直接添加並提交已追蹤的檔案
  • 查看變更差異bash git diff # 查看未暫存的變更 git diff --staged # 查看已暫存的變更
  • 暫存未完成工作bash git stash # 暫存當前變更 git stash pop # 恢復暫存的變更
  • 忽略檔案: 創建 .gitignore 檔案,列出不想追蹤的檔案或資料夾,例如: node_modules/ *.log

常見情境範例

  1. 開始一個新專案bash git init git add . git commit -m "初次提交" git remote add origin <URL> git push origin main
  2. 開發新功能bash git checkout -b feature-新功能 # 編輯檔案 git add . git commit -m "完成新功能" git checkout main git merge feature-新功能 git push origin main
  3. 修復 Bugbash git checkout -b fix-bug # 修復檔案 git add . git commit -m "修復 Bug" git checkout main git merge fix-bug

注意事項

  • 提交訊息要清晰:寫出有意義的訊息,例如「修復登錄頁面錯誤」而非「更新」。
  • 頻繁提交:小而頻繁的提交更容易管理。
  • 備份到遠端:定期推送至 GitHub 等平台,避免資料遺失。
  • 小心使用 git reset --hard:這會永久刪除變更,謹慎操作。

進階學習資源

  • 官方文件:https://git-scm.com/doc
  • 互動學習:https://learngitbranching.js.org/
  • GitHub 指南:https://guides.github.com/