Published on

Git與GitHub介紹及指令操作

Authors
  • avatar
    Name
    Ed Li
    X

一、簡介:什麼是 Git 和 GitHub?

  • Git: 一個「分散式版本控制系統」,讓開發人員可以追蹤檔案的變更,提供協同合作功能。
  • 不依賴單一伺服器,即使離線也能進行版本控制。
  • 可以使用快照(Snapshot)的方式記錄檔案變更,只儲存差異,節省空間。
  • GitHub: 以 Git 為基礎的「雲端版本控制服務平台」,提供遠端儲存空間、協作工具,以及專案管理功能。
  • 其它類似服務包含 GitLab、Bitbucket。

二、Git 的基本操作與概念

1. 版本控制的差異:集中式 vs. 分散式

  • 集中式版本控制 (如 SVN):依賴單一伺服器,離線時功能受限。
  • 分散式版本控制 (如 Git):每個開發人員都有完整的儲存庫副本,離線仍可操作,更能追蹤每次修改的變化。

2. Git 的核心工作流程

  • 工作區 (Workspace):開發人員編輯檔案的本地目錄。
  • 暫存區 (Staging Area):準備將變更納入下一次提交的區域。
  • 本地儲存庫 (Local Repository):儲存專案的歷史版本。
  • 遠端儲存庫 (Remote Repository):儲存在 GitHub、GitLab 等平台上的版本。
  • 基本步驟 (參考 Max行銷誌)
  • 初始化數據庫 (git init):在工作區建立 .git 目錄。
  • 「在目前工作區 (Workspace) 內建立一個 .git folder」。
  • 設定個人資訊:設定姓名和 Email,用於 Commit 紀錄
  • git config --global user.name "開發人員的姓名"
  • git config --global user.email "開發人員的Email"
  • 加入檔案至暫存區 (git add)
  • git add . (加入所有變更)
  • git add <檔案名稱> (加入特定檔案)
  • 提交變更至本地儲存庫 (git commit)
  • git commit -m "修改內容" (新增訊息)
  • 上傳變更至遠端儲存庫 (git push)
  • git push origin master (上傳到 master 分支)

3. 常見的 Git 指令

  • git clone: 從遠端儲存庫複製專案到本地。
  • git clone <repo URL>
  • git clone <repo URL> -b <branch name> (指定分支)
  • git clone <repo URL> <folder name/path> (指定下載名稱)
  • git status: 查看目前檔案的狀態。
  • git log: 檢視提交歷史。
  • git log --pretty=oneline (簡潔顯示)
  • git log --graph --pretty=format:'... (圖形化顯示)
  • git diff: 比較檔案變更。
  • git diff (工作區和暫存區差異)
  • git diff <commit ID> (與特定 commit 的差異)
  • git diff <commitA ID> <commitB ID> (比較兩個 commits 間的差異)
  • git fetch: 從遠端儲存庫下載最新變更,但不合併。
  • git pull: 從遠端儲存庫下載最新變更並合併到本地分支(相當於 git fetch + git merge)。
  • git pull --rebase (使用 rebase 合併)
  • git push: 上傳本地變更到遠端儲存庫。
  • git branch: 管理分支。
  • git branch (查看所有本地分支)
  • git branch -a (查看所有分支,含遠端分支)
  • git branch <Name> (建立分支)
  • git branch -d <name> (刪除分支)
  • git branch -m <name> (修改分支名稱)
  • git checkout: 切換分支或恢復到特定版本。
  • git checkout <Name> (切換分支)
  • git checkout -b <Name> (建立並切換分支)
  • git checkout <commit ID> <檔案名稱> (恢復檔案到指定版本)
  • git reset: 回到特定版本,可以搭配 --soft 或 --hard 參數。
  • git reset --soft HEAD~1 (保留工作區和暫存區)
  • git reset --hard HEAD~1 (丟棄工作區和暫存區)
  • git reset --hard <commit ID> (回到指定版本)
  • git reflog: 查看所有 commit 和 reset 的歷史紀錄。
  • git merge: 合併分支。
  • git merge <副分支> (fast-forward 模式)
  • git merge <副分支> --no-ff (no-fast-forward 模式)
  • git merge --abort (恢復合併前的狀態)
  • git stash: 暫存目前的變更。
  • git stash save "註解" (暫存並添加註解)
  • git stash list (查看暫存清單)
  • git stash pop <name> (回復並刪除暫存)
  • git stash apply <name> (回復但不刪除暫存)
  • git stash drop <name> (刪除指定暫存)
  • git stash clear (刪除所有暫存)
  • git tag: 標記特定 commit。
  • git tag (查看所有標籤)
  • git tag -l "v1.*" (列出符合條件的標籤)
  • git tag tag_name (輕量級標籤)
  • git tag -a v1.1 -m "version 1.1" (附註標籤)
  • git push origin --tags (上傳所有標籤到遠端)
  • git show: 顯示 commit 的詳細資訊。
  • git grep: 在檔案中搜尋符合條件的文字。
  • git clean: 刪除未追蹤的檔案。
  • git clean -n (預覽會刪除的檔案)
  • git clean -df (刪除未追蹤的檔案)
  • git cherry-pick: 選取其它分支中的 commit 並合併。
  • git cherry-pick <commit ID> (挑選特定 commit)
  • git cherry-pick A^..B (挑選 commit A 到 commit B 之間的 commits)
  • git revert: 回溯到某個 commit 的狀態,並建立一個新的 commit。
  • git revert <commit ID> (回溯到某個commit)
  • git revert HEAD (回溯到最新的 commit)
  • git rebase: 修改分支的基礎,可線性化 commit 歷史。
  • git rebase <master> (將目前分支的基礎變更為 master 分支)
  • git rebase -i HEAD~3 (互動式修改歷史)
  • git rebase --abort (取消 rebase)
  • git rebase --continue (繼續 rebase)
  • git rebase --onto <new base-commit> <current base-commit> (將目前分支 rebase 到 new base-commit)

4. SSH Key 和 Personal Access Tokens

  • SSH Key: 使用 SSH 連線 GitHub,避免每次都要輸入帳號密碼。
  • 私鑰 (id_rsa) 保密,公鑰 (id_rsa.pub) 可公開。
  • Personal Access Tokens: 當使用 HTTPS 時,可取代密碼來進行身份驗證。
  • 在 GitHub 設定中建立,可設定有效期限和權限。
  • 「這時候如果我們不想加入 ssh key, 也不想透過加入共同協做的方式, 可以透過這個 Personal Access Tokens (你可以把他想成臨時的權限)」

5. 改善大型儲存庫下載速度

  • 使用 --depth 參數只下載最近的 commit 歷史紀錄。
  • git clone [email protected]:example/example.git --depth 1
  • 使用 --no-single-branch 參數下載所有分支的最新 commit。
  • git clone [email protected]:example/example.git --depth 1 --no-single-branch
  • 使用 -b 指定分支。
  • git clone [email protected]:example/example.git --depth 1 --no-single-branch -b stable/x.x.x

6. 工作區與暫存區的觀念

  • git add: 把要送出的文件放到暫存區。
  • git commit: 把暫存區的修改內容送到目前的分支上。

7. 解決衝突

  • 當多人修改同一檔案時,可能會發生合併衝突。
  • Git 會在檔案中標記出衝突的部分。
  • 需要手動修改檔案,移除衝突標記後再提交。
  • 「通常我們會手動下去修改衝突 conflicts,然後再加個 commit」
  • 使用 git merge --abort 或 git reset --hard HEAD 可取消合併。

8. .gitignore 檔案

  • 設定 Git 忽略追蹤的檔案或目錄。
  • 可透過在根目錄建立 .gitignore 檔案,在其中寫入要忽略的文件名稱,git 將自動忽略這些檔案。
  • 「只要在 Git 工作區的根目錄下新建一個特殊的 .gitignore 文件 ,然後把要忽略的文件 ( 檔案 ) 名稱輸入進去, Git 就會自動忽略這些文件。」
  • 可使用 git update-index --skip-worktree <file> 暫時忽略檔案變更。
  • 「適合使用在 settings 的檔案,有時候我們在開發的時候,都會有自己的設定,但這個設定未必是大家都需要的,這時候就可以暫時先忽略這個檔案的改變。」
  • 可使用 git rm --cached <file> 將已經追蹤的文件從索引中移除。
  • 「假設今天 file 這個檔案已經被 commit 到 git 中了,但是我想把他加入 .gitignore,這樣該怎麼辦:question:」

9. 設定 Git 快捷鍵 (Alias)

  • 可以使用 git config --global alias.<alias_name> <command> 來建立自定義的快捷指令。
  • 例如: git config --global alias.st status,即可使用 git st 代替 git status
  • Oh-My-Zsh 提供許多預設的 Git 快捷鍵設定。
  • zsh 存放 git alias 的位置:~/.oh-edli01-zsh/plugins/git/git.plugin.zsh

10. Git Submodule 和 Subtree

  • Submodule: 將其它 Git 儲存庫加入為子目錄。
  • Subtree: 將其它 Git 儲存庫合併到當前專案的子目錄。
  • 兩者都用於管理專案中的外部依賴項。

三、Git 分支 (Branch) 的使用

  • 分支的目的:
  • 允許多人同時開發不同功能或修正錯誤。
  • 支援多個版本發佈和維護。
  • 基本操作:
  • 建立分支:git branch <Name>
  • 切換分支:git checkout <Name> 或 git checkout -b <Name>
  • 查看分支:git branch 或 git branch -a
  • 刪除分支:git branch -d <name>

1. 合併分支

  • Merge: 將不同分支的變更合併到一起。
  • Fast-forward: 簡單地將指標移動到最新 commit (較不重要 commit 可使用)。
  • No-fast-forward: 產生合併 commit,保留分支歷史 (較重要 commit 可使用)。
  • Rebase: 將分支的基礎變更為另一個分支,線性化 commit 歷史。
  • 避免不必要的 merge commits,維持 commit 紀錄的整齊。
  • 小心使用,避免修改到他人正在使用的分支。
  • 可用於修改歷史 commit 紀錄 git rebase -i HEAD~2

2. 多人協作流程

  • 開發人員從 master 分支建立新分支。
  • 在新分支上進行開發和修改。
  • 將變更提交到自己的分支。
  • 提交 Pull Request (合併請求) 給團隊成員。
  • 團隊成員審核 Pull Request,確認沒問題後合併到 master 分支。
  • 使用 git pull 更新本地的 master 分支。

3. Git Flow

  • 一種分支管理策略,區分不同用途的分支,如 master, develop, feature, release, hotfix 等。

四、多人協作與 GitHub

  • 協作者: 在 GitHub 上新增協作者,可共同開發專案。
  • Pull Request: 請求將自己分支的變更合併到其它分支。
  • Fork: 複製別人的專案到自己的帳號,方便進行修改和貢獻。

五、版本回溯

  • git reset:
  • 類似「Time Machine」,可搭配 --soft 和 --hard 參數。
  • --soft 模式:只移動 HEAD 指標,保留工作區和暫存區。
  • --hard 模式:丟棄工作區和暫存區。
  • git checkout:
  • 將 HEAD 移動到指定 commit,但不移動任何分支。
  • 「checkout 就是一個負責移動 HEAD 指到不同地方的指令」
  • 可從特定 commit 建立新分支。
  • 使用git reflog可還原reset造成的歷史紀錄抹除。

六、其它注意事項

  • Linux 環境: 忽略檔案權限 (chmod) 的改變 (git config core.fileMode false).
  • Windows/Linux 換行符號: 設定 core.autocrlf (true for Windows, input for Linux/Mac)。
  • 一次 Push 到多個遠端: git remote set-url --add origin <url>
  • 可使用 git push --force-with-lease,避免覆蓋他人 commit。
  • 當執行 git pull --rebase 遇到衝突時,可使用 git rebase --abort 取消。
  • 可以使用 git pull --rebase --autostash 來自動將目前的變更存到 stash 中。

七、總結

Git和GitHub是軟體版本控制的最佳好幫手,它們能有效管理程式碼版本、實現協同合作、並且追蹤專案的變更歷史。透過了解 Git 的核心概念與指令,開發人員可以更有效率且更穩健的進行軟體開發。

八、參考資料

Git達人教你搞懂GitHub基礎觀念

維基百科-Git

維基百科-Github