# Git 筆記 ###### tags: `Programming` > Main contributer > [name=Haouo] 主要整理一些關於 __Git__ 和 __Github__ 的基礎用法 :::info 如果內容有任何錯誤需要更正,或是想要新增一些東西 都非常歡迎! ::: # 目錄 [TOC] # 基礎 Git 觀念 ![](https://i.imgur.com/2UhnIn0.png) ## 1. Working directory(_工作目錄_)、Staging area(_暫存區_)和 Local repository(_儲存區_) >你可以想像你有一個倉庫,在倉庫門口有個小廣場,這個廣場的概念就像暫存區一樣,你把要存放到倉庫的貨物先放到這邊(`git add`,staging area),然後等收集的差不多了就可以打開倉庫門,把在廣場上的貨物送進倉庫裡(`git commit`,local repo),並且記錄下來這批貨是什麼用途的、誰送來的。 [name=高見龍] __倉庫前的小廣場 -> Staging area__ __倉庫 -> Local repository__ 而 Remote 則是遠端(不在電腦 local 端)的儲存庫,例如 Github 上面的 Repository 就是一種 Remote repo ## 2. When to commit ? >基本上什麼時候 commit 都可以,你要把東西都完成才提交,或是一直不斷地提交都可以,但是有一套好的規則、習慣會比較好。 ==常見的 Commit 的時間點有==: 1. __完成一個「任務」的時候__:不管是大到完成一整個電子商務的金流系統,還是小至只加了一個頁面甚至只是改幾個字,都算是「任務」。 2. __下班的時候__:雖然可能還沒完全搞定任務,但至少先 Commit 今天的進度,除了備份之外,也讓公司知道你今天有在努力工作。(然後帶回家繼續苦命的做?) 4. __你想要 Commit 的時候就可以 Commit__。 > [name=高見龍] # 常用 Git 指令 ## 1. `git init` 初始化一個資料夾,建立 Local Repository 如此一來 Git 才可以對這個資料夾進行版本控制 ## 2. `git add` 不論去新增、刪除、修改檔案之後,這些新的狀態(status)都不會自動被丟到 staging area 內,所以要透過 `git add` 這個指令來把這些新的狀態加入暫存區 ### 2.1 基礎用法 - __`git add <file name>`__ 加入指定的檔案到 staging area - __`git add .`__ & __`git add --all`__ 一次加入所有的檔案到 staging area Ps: 在較新版本的 Git 中,這兩個指令基本上沒有差別 ### 2.2 ==常犯錯誤== 想像一下這個情境: 1. 你新增了一個檔案叫做 abc.txt。 2. 然後,執行 git add abc.txt 把檔案加至暫存區。 3. 接著編輯 abc.txt 檔案。 __接下來不可以直接 commit!!!__ 因為你第三步驟修改的東西並沒有放進 staging area,所以要再 add 一次才可以 ## 3. `git commit` 當你確認目前階段任務已經完成,而且 staging area 內的更改內容都是你想要提交到 local repo 的內容時,就可以用 `git commit` 這個指令 ### 3.1 基礎用法 - 單純 __`git commit`__ 這種用法會進入 vim 編輯器內,==需要自己打上需要提交的文字內容==之後才送出 - __`git commit -m <commit message>`__ 這種用法就==不會進入 vim 編輯器內==,只要把想要一併提交的文字訊息接在 option `-m` 後面即可 3.1 - __`git commit -a -m <commit message>`__ 當你剛剛編輯完一些文件的時候,並且已經確認更改內容無誤,要直接 commit 時,但又不想先 add 再 commit? 直接加上參數 `-a` 就可以==把 add 和 commit 合併在一起== - __`git commit --allow-empty -m <commit message>`__ 參數 `--allow-empty` 可以允許就算沒有任何東西在 staging area 內需要被 commit 的狀況下,也可以 commit - __`git commit -amend`__ 可以修改最近一次 commit 的訊息 也可以用 __`git commit -amend -m <commit message>`__ 直接加上要補充的 commit message - ==想要新增一個空資料夾,並且 commit 到 local repo== 因為 git 只追蹤檔案 “內容” 的變化,所以單純新建一個資料夾,git status 不會發生變化 可以利用一個==小技巧==:在資料夾下面新增一個檔案 `.keep`,指令:`touch .keep` 如此一來 git 就可以抓到這個新的資料夾 ## 4. `git branch` ### 4.1 ==為什麼要使用分支(Branch)?== > 在開發的過程中,一路往前 Commit 也沒什麼問題,但當開始越來越多同伴一起在同一個專案工作的時候,可能就不能這麼隨興的想 Commit 就 Commit,這時候分支就很好用。例如想要增加新功能,或是修正 Bug,或是想實驗看看某些新的做法,都可以另外做一個分支來進行,待做完確認沒問題之後再合併回來,不會影響正在運行的產品線。 > [name=高見龍] Ps:一個 local repo 會預設建立一個 branch,名為 `master`,這個 branch 是個可以被刪除,或是改名的! ### 4.2 基礎用法 - __`git branch <branch name>`__ 會直接建立一個新的 branch - __`git branch -m <branch name brfore> <branch name after>`__ 可以把已經存在的 branch 改名 - __`git branch -d <branch name>`__ 可以刪除已經存在的 branch,包含預設的 master branch __如果 branch 因為一些原因不能直接刪除怎麼辦?__ 可以用 __`git branch -D <branch name>`__ 強制刪除 差別在於 d 是大寫還是小寫,如果是大寫則強制執行 - 切換分支 參考 `git checkout` ## 5. `git checkout` `git checkout` 這個指令主要有三個功能 1. __恢復被修改的檔案__ git 會把 staging area 內的內容拿來覆蓋目前 working directory 的內容 - ==__重要觀念__== 正常在沒有 add 任何狀態到 staging area 的時候,此時 staging area 的狀態會和最後一次 commit 時的狀態一致 但是當你已經有 add 一些新的狀態到 staging area 內時,再用 checkout 指令恢復檔案時,Git 就會用 staging area 內的狀態來覆蓋 working directory,而不是最後一次 commit 的狀態 2. __切換分支(branch)__ 嗯。就是切換分支 3. 切換 __HEAD__ 指向的地方 > HEAD 是一個指標,指向某一個分支,通常你可以把 HEAD 當做「目前所在分支」看待。在 .git 目錄裡有一個檔名為 HEAD 的檔案,就是記錄著 HEAD 的內容。 > [name=高見龍] __通常 HEAD 就是指向某個分支中的某次 commit__ __預設情況下,HEAD 會指向 master branch 中最新的一次 commit__ ![](https://i.imgur.com/NrOv6e4.png) ### 5.1 基礎用法 - __恢復被修改的檔案__ - __`git checkout <file name>`__ 這個指令可以指定你要恢復的檔案,用目前 staging area 的狀態覆蓋 working directory - __`git checkout .`__ 和上一個指令一樣,差別在於可以一次恢復所有檔案 - __`git checkout HEAD~<an integer> <file name>`__ 這個指令可以把指定的檔案用該次 commit 前幾次的 commit(視輸入的整數而定)的狀態來覆蓋目前的 working directory,並且一併更新 staging area,所以接下來只要直接 `git commit` 即可 - __`git checkout HEAD~<an integer> .`__ 和上一個指令一樣,差別只在於他會做用於全部檔案 - __切換分支__ - __`git checkout <branch name>`__ 切換到指定的分支下 - __`git checkout -b <branch name>`__ 加上參數 `-b` 的特別之處在於,如果你輸入的 `<branch name>` 是一個不存在的分支,他會自動幫你建立一個同名的新分支 - __切換 HEAD 所指的的 commit__ - __`git checkout HEAD~<an integer>`__ 可以發現後面沒有加上 `<file name>` 或是 `.`,如此一來就只是單純的切換 HEAD pointer 所指的 commit ### 5.2 特殊情境 - __我可以回到過去的某次 commit 再開一個新分支出來嗎?__ 1. 先利用 `git checkout HEAD~<an integer>` 切換到你想要的那次 commit 2. 利用 `git branch <branch name>` 從該次 commit 直接創立一個新分支 3. 如此一來,就可以在這個新分支下繼續 commit 了 ![](https://i.imgur.com/LJ1yd0R.png) 效果大概就是這樣 `Develop` 這個分支是利用 `git chechout HEAD~2` 指令先回到第一次 commit,再利用 `git branch develop` 建立新分支,再繼續開發 ## 6. `git merge` ## 7. `git reset` ### 7.1 重要觀念 > Reset 這個英文單字的翻譯是「重新設定」,但事實上 Git 的 Reset 指令用中文來說比較像是「前往」或「變成」,也就是「go to」或「become」的概念。當執行這個指令的時候: > > `git reset HEAD~2` > > 這個指令你原本可能會解讀成「請幫我拆掉最後兩次的 Commit」,但其實用「拆」這個動詞只是我們比較容易理解而已,事實上並沒有真的把這個 Commit「拆掉」(放心,所有的 Commit 都還在)。 > > 正確的說,上面這個指令應該要解讀成「我要前往兩個 Commit 之前的狀態」或是「我要變成兩個 Commit 之前的狀態」,而隨著使用不同的參數模式,原本的這些檔案就會丟去不同的區域。 > > 因為實際上 git reset 指令也並不是真的刪除或是重新設定 Commit,只是「前往」到指定的 Commit,那些看起來好像不見的東西只是暫時看不到,但隨時都可以再撿回來。 > [name=高見龍] __基本上可以不用 reset 就不要用,多數狀況都可以用 checkout 來完成任務,除非真的有一些 commit 是要捨棄的__ __特別是在多人協作的時候,隨意 reset 可能會造成別人的 branch 全部被你丟掉__ ## 8. `git log` 這個指令可以顯示目前這個 branch 下的歷史提交(commit)紀錄,是一個非常基礎且常用的指令 ### 8.1 基礎用法 - __`git log`__ 顯示最基本的 commit information、commit message - __`git log --graph`__ 附加選項 `--graph` 可以顯示出簡單的分支、合併線圖 - __`git log -p`__ 詳細顯示每筆 commit 的修改內容 - __`git log -<an integer>`__ 限制要顯示出最後幾筆 commit - __`git log --stat`__ 和 `-p` 差不多,差別在於顯示的內容比較簡略 ## 9. `git status` __用來顯示目前 Working directory 和 Staging Area 的狀態__ ### 9.1 基礎用法 - __`git status`__ - __`git status -s`__ `-s` 等同 `--short` 顯示較少內容 - __`git status -v`__ `-v` 等同 `--verbose` 顯示更完整的內容 詳細介紹可以參考下面的 Git Documentation >In addition to the names of files that have been changed, also show the textual changes that are staged to be committed (i.e., like the output of `git diff --cached`). If `-v` is specified twice, then also show the changes in the working tree that have not yet been staged (i.e., like the output of `git diff`). >[name=Git Documentation] ## 10. `git remote` 用來管理遠端版本庫(Repository)的指令 ### 10.1 基礎用法 - __`git remote add <remote name> <URL>`__ 新增一個遠端 repo - __`git remote`__ - ## 11. `git push` ## 12. `git reflog` ## 13. `git pull` ## 14. `git fetch` ## 15. `git clone` ### 15.1 基礎用法 - __`git clone [URL]`__ # Reference 1. [為你自己學Git](https://gitbook.tw/ "link") 2. [猴子都能懂得 Git](https://backlog.com/git-tutorial/tw/ "link") 3. [W3HEXSCHOOL](https://w3c.hexschool.com/git/9a164fbe "link") 4. [細說 git reset 和 git checkout 的不同之處](https://medicineyeh.wordpress.com/2015/01/22/%E7%B4%B0%E8%AA%AAgit-reset%E5%92%8Cgit-checkout%E7%9A%84%E4%B8%8D%E5%90%8C%E4%B9%8B%E8%99%95/ "link")