Git 技術整理

tags: Git

AndyChiangSun, Jan 17, 2021 3:15 PM

我看的教學:六角Git & GitHub 教學手冊

Git

認識Git

簡單講,Git可以幫你記下哪些時候,做了哪些變更,並可以隨時回頭看原先的版本,避免開一堆副本搞得眼花撩亂。

Git下載流程

而SourseTree則是讓Git視覺化,方便使用。

SourseTree載點

使用終端機

使用終端機才能真正學會Git的指令,以及理解什麼指令在做什麼事情。

  • Win:Git Bash
  • Mac:終端機

常用終端機指令

Windows MacOS / Linux 說明
cd [路徑] cd [路徑] 前往資料夾路徑
cd pwd 取得目前所在的位置
dir ls 顯示資料夾裡的檔案
mkdir mkdir 新增資料夾
無指令 touch 開新檔案
copy cp 複製檔案
move mv 移動檔案
del rm 刪除檔案
cls clear 清除畫面上的內容

設定個人資料

  • 輸入姓名:git config --global user.name "your name"
  • 輸入個人的 email:git config --global user.email "your email"
  • 查詢 git 設定內容:git config --list

基本架構

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →

Git 建立本地數據庫

git init

想要建立本地數據庫時:

  1. 先在你的電腦新增一個資料夾
  2. 終端機輸入這個指令cd <該資料夾的路徑>
  3. 輸入git init指令

查詢當前狀態

git status

可以知道檔案目前的狀態,git的狀態有以下圖片的這四種。

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →

將檔案加入索引

git add <檔案名稱>

比較常用的是git add .,將所有檔案全部加入索引。

提交新版本

git commit -m "<填寫版本資訊>"

目前在索引內的檔案會被提交成一個新版本,填寫版本資訊則是為了在你未來回頭看的時候,知道這次commit在幹嘛。

查詢版本

git log

你如果得到以下回饋,代表你有成功commit上去了。

commit b6c3c771cd8939bcd25a8c50089fdf0cd3eab98d (HEAD -> master)
Author: 你的姓名 <你的 Email>
Date:   你的版本更新時間

    版本資訊

Git 建立遠端數據庫

兩個熱門的遠端數據庫比較

  • GitHub:擁有 GitHub Pages 功能,可擁有私人數據庫,免費方案是 3 人以下,適合想要有一個公開對外網站的團隊。
  • Bitbucket:可擁有私人數據庫,免費方案是五人以下團隊,適合公司專案的小型團隊。

我這裡都用GitHub當作練習

基本上要連上遠端數據庫有兩種方式,兩種都差不多。

  1. 先建立好本地端,建立新的遠端,然後本地端綁上遠端,將本地的檔案push上去。
  2. 先建立好遠端,然後clone(之後講)遠端在自己電腦,直接在clone下來的資料夾內新增你的檔案,git會自動幫你連上遠端。

本地數據庫綁定遠端數據庫

git remote add <遠端數據庫簡稱> <url>
// ex: git remote add origin <url>

遠端數據庫簡稱,預設為origin。

推送到遠端數據庫

git push <數據庫簡稱> <分支名稱>
// ex: git push origin main

複製遠端數據庫

git clone <複製的網址>
  1. 在你的GitHub遠端數據庫,找到下圖的這個連結:
    Image Not Showing Possible Reasons
    • The image file may be corrupted
    • The server hosting the image is unavailable
    • The image path is incorrect
    • The image format is not supported
    Learn More →
  2. 終端機先cd到想要複製的資料夾位置,然後輸入clone。(注意!不會產生新的資料夾)
  3. 會自動綁定遠端數據庫

抓取遠端更新

git fetch

會發生在多人協作時,如果遠端的進度比本地端還要前面,這個指令就會將遠端資料抓下來,並更新再本地端,git fetch之後會長這樣:

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →

你會發現本地的master還在原先的位置。

本地同步更新

git pull

其實 git pull = git fetch + git merge
也就是說, git pull 就是在 git fetch 後,將 master 給 merge 到 origin/master 而已,結束後長這樣:

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →

Git 分支

HEAD的相對位置
  • 往前推一個版本:HEAD^,幾個^就往前推幾個版本。
  • 往前推N個版本:HEAD^N

^也可以替換為~

HEAD脫離
git checkout <目前分支的commit SHA-1碼>

Image Not Showing Possible Reasons
  • The image file may be corrupted
  • The server hosting the image is unavailable
  • The image path is incorrect
  • The image format is not supported
Learn More →

ORIG_HEAD

Git會幫你紀錄上一個HEAD的位置,因此在做一些危險操作時,可以使用ORIG_HEAD退回上一步。

移動HEAD位置

git checkout <分支名稱/commit SHA-1碼>

HEAD就是目前指向的版本,透過此指令可以移動到想要的位置。

建立分支

git branch <分支名稱>

如此一來,就會多出一個新的分支,初始的位置就是當前HEAD的位置。如果想在新分支上新增commit,記得用git checkout 切換到新的分支上喔!

直接移動分支位置
git branch -f <分支名稱> <HEAD的相對位置/commit SHA-1碼>
  • 相對位置:HEAD的相對位置
  • 絕對位置:版本名稱

合併分支

git merge <分支名稱>

此指令會將當前分支,合併到git merge <>輸入的分支中。
常見作法如下:

  1. git checkout切換至較舊的分支
  2. 輸入git merge <較新的分支>
  3. 完成合併後,較舊的分支便有較新分支的commit
合併-快轉模式


當master沒有作任何更動時合併到dev,此時不會產生新的commit,這種情況我們稱為快轉模式,當然反之就有非快轉模式。

合併-非快轉模式


當master在分支之後有新的更動時,便會產生兩條相異的分支,此時合併會產生新的commit(如圖上C6),我們稱為非快轉模式

--no-ff
git merge dev --no-ff

如果想要將master合併到dev上,卻又不想發生快轉模式,就要加入這個指令。

另一種合併方式
git rebase <分支名稱>

rebase的概念是,因為上圖 cat 和 dog 兩條分支都源自於 master ,所以當我們使用rebase時,Git就會先複製一份 cat 的分支,然後重新給予commit編號並接在 dog 的後面。如此一來便合併便不會產生新的commit,而 cat 舊的commit則會在保留一段時間後,被Git回收。
要如何復原? 會用到之後講的 reflog 或者是 reset ORIG_HEAD

但注意,使用rebase容易搞混,因此不推薦使用。

這裡提供一個方便的工具,學習如何活用Git分支:Learn Git Branching

本地分支衝突

並不是每次合併都是順順利利的,當兩條分支修改同一行Code時,就會發生衝突。

可能會遇到這種情況


master和dev兩條分支同時更改了h1的樣式,系統便會提示出現衝突:

❯ git merge dev    
Auto-merging all.css
CONFLICT (content): Merge conflict in all.css
Automatic merge failed; fix conflicts and then commit the result.

那麼,如何解決衝突?

  1. checkout 到 master 後,輸入 git merge dev
  2. 發生衝突,all.css 變成 Unmerged 狀態
  3. 修改 all.css 後,重新加入到索引 git add all.css
  4. 透過 git status 指令觀察,是否可以重新提交
  5. 輸入 git commit 提交,並撰寫 commit 訊息,完成本次合併

遠端協作分支衝突

這件事會常發生在多人協作的時候

  1. A和B協作,A先push上共同GitHub
  2. B後來也要push上GitHub,於是她需要先把檔案給pull下來
  3. 但B發現A的檔案和他的發生衝突了!!

那麼,如何解決衝突?

  1. B必須先修正衝突,commit一個新的在本地端
  2. 然後push上GitHub,在原先A檔案的後面

Git 還原

還原版本,且保留檔案

git reset <HEAD的相對位置/commit SHA-1碼>

還原版本,且不想保留檔案

git reset <HEAD的相對位置/commit SHA-1碼> --hard

reset vs. checkout

  • reset:帶著HEAD指向的分支移動至指定版本,HEAD脫離時無法使用。
  • checkout:移動HEAD,不會帶動分支移動。

還原你的還原

人總是會手賤犯錯,如果不小心還原了不想還原的版本時該怎麼辦?

git reflog

會顯示出先前的所有動作,複製復原的那次commit編號,再reset回去就好了,git都會幫你做紀錄,無須擔心檔案會不見啦。

紀錄還原

git revert <commit SHA-1碼>

Git 會幫你還原這個commit更新的內容,但他不會幫你刪除,而是在新增一個還原後的commit(當然SHA-1碼也是新的)。

還原時機統整

新增檔案時,檔案還沒加入追蹤,想清空工作目錄
  • 顯示要被清除的檔案:git clean -n
  • 強制清除檔案:git clean -f
檔案已加入追蹤,想還原工作目錄
  • 單一檔案指令 :git checkout -- <file>
  • 全部檔案指令:git checkout .
檔案加入到索引,想退到工作目錄
  • 指令:git reset HEAD

Git 暫存

如果你A專案正寫到一半,突然老闆叫你修B專案的Bug,該怎麼辦? A專案還沒寫完又不能commit!
這時就該用到git stash了。

stach類似stack的概念,最後加入的記錄會在頂端({0})。

暫存儲存當前目錄

git stash

瀏覽 git stash 列表

git stash list

還原暫存

git stash pop

清除最新暫存

git stash drop

清除全部暫存

git stash clear

指定特定暫存紀錄

<stash指令> stash@{n}    //n就是list上的編碼

IT邦邦忙 - git stash 暫存檔案

GitHub

README.md(說明文件)

使用MarkDown語法,會直接顯示說明文件在專案底下。

為圖片加上超連結

[![google]](https://google.com)
[google]:http://www.google.com/img/logo.jpg "GoogleLogo"

插入GitHub倉庫內的圖片

https://github.com/ 你的使用者名稱 / 你的專案名 / raw / 分支名 / 存放圖片的資料夾 / 該資料夾下的圖片

GitHub Page(靜態網頁)

這個地方可以展示你的網頁!(但只有靜態網頁)

  1. 建立一個本地數據庫,存著你的靜態網頁
  2. 跟這之前的教學,在GitHub上建立一個遠端數據庫,並且將綁上本地端。
  3. push檔案上GitHub
  4. 成功後,到GitHub數據庫>Settings>GitHub Pagessourse選擇master,如下圖
  5. 完成後,再回到GitHub Pages,你會看到如圖的畫面,表示你成功了,網址要記好,它就是你靜態網頁的網址。
  6. 若要更新內容,只要修改完後commit+push新的版本上來就好了。

我的範例

  1. 個人小履歷
  2. 甜點商家官網

.gitignore(忽略檔案)

這個檔案要新增在你的專案裡面,功能是讓記錄在.gitignore內的檔案不會被版本控制,通常是用於插件,格式為:

index.html/
color.css

這樣一來,index.html/color.css這兩個檔案就不會有版本控制了。

git status可以查詢哪些檔案被忽略。

PR(Pull requests)

當你在逛GitHub時,看到A的程式碼寫的不錯,但有一點小錯誤,你想幫他修改,該怎麼做?

  1. 此專案的左上角會有一個fork按鈕,點選將此專案插入一份到自己的GitHub中。
  2. 將自己GitHub上的專案clone到自己的電腦。
  3. 修正程式碼
  4. push上自己的GitHub
  5. 然後選擇Pull requests>New pull request>Create pull request,輸入修正訊息後按確定。
  6. 此時A那端就會收到你的pull request了,他看過如果覺得沒問題,他就會merge,並且加入一個merge過後的commit。
  7. 你寫的程式碼就會出現在A的專案中了!

GitHub Flow

GitHub Flow是一個由GitHub所規範的一個流程,許多團隊都會導入這套流程,讓開發順利進行。

流程

  1. clone 遠端資料。
  2. 在 master 建立分支來新增功能。
  3. 開始開發功能。
  4. 發 PR (Pull Request) 申請合併。
  5. 討論與檢視程式碼。
  6. 部署(Deploy)。
  7. 合併(Merge)。

規範

  1. 任何在 master 上的 commit 都是可以部署的。
  2. 假使程式碼需要討論,請 PR 後在 comment 進行討論。
  3. 如果想開發功能,務必新開分支。

Understanding the GitHub flow

補充連結

進階補充

GitHub desktop vs. SourseTree

GitHub desktop

  • 優點:與GitHub連結良好(廢話,就是GitHub自己推出的),檔案可預設以VScode開啟。
  • 缺點:沒有視覺化分支,沒有還原

SourseTree

  • 優點:有視覺化分支,還原容易,有簡體中文,但還是覺得英文比較好XD
  • 缺點:好像沒缺點(?

GitHub desktop和SourseTree比較

VScode Git 外掛

其實VScode上也有外掛可以使用git指令,基本的add、commit、push都可以,優點是如果你本身就是用VScode寫程式,不需要額外開其他程式,但缺點是沒有圖形化介面,可能會搞不清楚現在的branch長怎樣?

SSH金鑰

除了HTTP外的另外一種連接GitHub方式,因為有一組公鑰和私鑰做雙重身分認證,比起HTTP更加安全。

設定SSH的步驟有點複雜,這裡就不贅述了,可以參考以下網址:
SourceTree 連接 GitHub, Bitbucket (使用 SSH) 於 Windows