為什麼要使用Git版控?
不管老手或新手在寫程式的時候都會犯錯,有時錯誤嚴重到會希望有一部時光機,讓時間倒流回犯錯之前。正因為這種錯誤,每個程式工程師都應該在開發專案中使用版本控制;不使用版本控制的後果,就等於電腦不備份一樣,一個突然的意外或資料遺失就會讓整個專案受到極大影響。
版本控制能讓你回溯之前的專案版本,可以回復遺失的資料,或是查看程式碼的進程。另外,使用版本控制後,與其他人合作同一個專案就容易得多。
我剛開始學Git以為 GitHub 和 Git 是同一樣東西,但這是錯的。Git 是一個在你自己電腦本機端運行的版本控制系統,而 GitHub 則是一個線上服務,讓你將 Git 版本資訊儲放至雲端,就像是 iCloud 雲端硬碟,但它是專屬於程式碼的應用,而且功能更強大。
下圖示 Git 是如何運作的。
Working Directory 存放你正在編輯的檔案
Staging Area 則存放 commit (提交) 前的檔案
commit 這些檔案時,檔案就會加到你的本機儲存區
當你進行 push,就會將你的本機儲存區和遠端儲存區同步,我們用的遠端儲存區就是 GitHub。每次進行 push,就可將在本機端的改動加到遠端儲存區;換而言之,進行 pull 的話,就可以將在遠端儲存區的改動,加入到本機儲存區中。
舉個例子:
假設你和夥伴正在合作開發一個簡單的專案,當你今天想新增功能的部分,首先你需要從遠端儲存區進行 pull,確保你的版本已包含其他夥伴做過的程式碼改動。然後,你可以開始編寫程式碼,此時檔案就在你的 working directory。當你完成了一個功能、或是某個重要的部分後,就 git add 檔案到 staging。如果你加入了任何檔案或圖片,亦要把它們加到 staging。現在你可以準備 commit 了,commit 的時候,請加入注釋說明做過的改動。最後,你可以用 git push 同步本機儲存區與遠端區。你的夥伴也需要進行 pull,這樣就可以知道你在 setting 頁面做了什麼改動。
說明一些 Git 的指令:
git init: 這個指令可以初始化 Git 專案目錄
git status: 這個指令可以顯示你 git 儲存區的狀態。在你的指令列中,設定了沒被追蹤的檔案 (不在 staging) 顯示為紅色,有被追蹤的檔案 (在 staging) 則顯示為綠色
git add: 這個指令可以把你的檔案加到 staging
git commit: 這個指令可以 commit 你在 staging 的檔案到本機儲存區。
git push: 這個指令可以將你做的改動 push 到遠端儲存區 (GitHub)。
git pull: 這個指令可以將改動從遠端儲存區 pull 回來。你與夥伴開發同一個專案時,你會需要將其他夥伴的改動 pull 回來,並同步至你的本機儲存區中。
git checkout:在 Git 裡面,Checkout 代表著切換分支。比如說,當我想要處理主要分支的另一個功能,我就要 checkout 主要分支,在主要分支編寫程式碼;當我想要開發 resverse,我就要 checkout Reserve 分支再繼續編寫。
以下是我整理出來的筆記
# windows-
$ which git # 查電腦裡git版本
$ which apt-get install git
$ sudo sudo apt-get install git #sudo獲得權限
# Mac-
# Homebrew安裝
$ brew install git
$ git --version # 查詢git版本
$ git config --list # 查看git config
$ git config --global user.name "user" # 設定User訊息
$ git config --global user.email "user@gmail.com"
初始化git
$ mkdir git-demo # 建立新資料夾git-
$ cd demo # 進入git-practice資料 夾
$ git init # 初始化GIT版本控制
$ git status # 查看目前狀態
$ touch 01.html # 建立一個01.html檔案
加入暫存區 add
$ git add 01.html # 將01.html加入暫存區
$ git add *.html # 所有.html檔案加入暫存
$ git add --all # 將所有檔案加入暫存區
$ git add . # 將所有檔案加入暫存區
commit
$ git commit -m "init commit" # 創建commit命名init commit
$ git commit --allow-empty -m "blank" # 允許創建空的commit
$ git commit -a -m "update content" # 將未add檔案commit
Git 新增/改名/移除
$ git rm welcome.html # 移除
$ git rm welcome.html --cached # 將此檔案Untracked
#(不是真的刪除)
$ git mv hello.html world.html # 重新命名
# 追加檔案並重新命名上一次commit
$ git commit --amend -m "Welcome To Facebook"
# 追加檔案不重新命名上一次commit
$ git commit --amend --no-edit
查看 log
$ git log # 查看紀錄
$ git log --oneline --graph # 查看oneline/graph格式化紀錄
$ git log --oneline --author="Sherly"
$ git log --oneline --author="Sherly\|Eddie"
$ git log --oneline --grep="wtf"
# 搜尋在所有Commit檔案中符合特定條件的
$ git log -S "Ruby"
# 搜索時間條件
$ git log --oneline --since="9am" --until="12am"
$ git log --oneline --since="9am" --until="12am" --after="2019-01"
branch 分支相關
$ git branch # 查看目前Branch
$ git branch BranchName # 建立名為BranchName的分支
$ git branch -m BranchName BranchNewName # 重新命名
$ git branch -d BranchName # 刪除branch
$ git branch -D BranchName # 強制刪除即使分支尚未被合併
$ git checkout BranchName # 切換分支
$ git checkout -b BranchName # 建立且切換分支
$ git checkout -b bird 654fce7 # 在commit:654fce7建立且切換分支
$ git branch BranchName 654fce7 # 在commit:654fce7建立分支
$ git merge BN # 將當前分支合併到BN分支
$ git merge BN --no-ff # 當前分支合併到BN分支,不快轉
$ git merge b234b6a # 將當前分支合併到commit:b234b6a
$ git rebase BN # 合併至BN並且以BN當作參考基準
checkout (移動head去查看)
$ git checkout 01.html # 01.html回到上一版
$ git checkout . # 所有檔案回到上一版
$ git checkout HEAD~2 01.html # 02.html回到上兩版
$ git checkout HEAD~2 . # 所有檔案回到上兩版
$ git blame FILENAME # 查看每一行程式碼修改歷史
$ git blame -L 5,10 FILENAME # 同上指定行數5~10
$ git log -p FILENAME
reset
$ git reset e12d8ef^ # reset到commit:e12d8ef的上一版
$ git reset master^ # reset到master分支的上一版
$ git reset HEAD^ # reset到head的上一版
$ git reset HEAD~2 # reset到head的上2版
$ git reset b174a5a --hard # 用--hard模式reset
#(完全清除目錄以及暫存區)
$ git reset HEAD^ --hard
$ git reset ORIG_HEAD --hard # 回到上一個關鍵版本
$ git reflog # 查看歷史紀錄(一個月內)
merge解決衝突
$ git rebase --continue # 當遇到合併衝突時,解決後繼續
$ git checkout --ours animal.jpg # 當遇到衝突時,選擇目前分支的檔案
$ git checkout --theirs animal.jpg # 當遇到衝突時,選擇合併分支的檔案
tag標籤
$ git tag 1.0.0 23d54dfc # 將commit:23d54dfc 建立tag 1.0.0
$ git checkout 1.0.0 # 查看1.0.0標籤版本
GitHub
$ git remote add origin url # 在遠端加入origin節點
$ git push origin master # 當前分支推到遠端origin的master分支
$ git push origin aaa:master # 將本地aaa分支推到遠端origin的master分支
$ git push -u origin master # -u設定upstream,之後可以直接推送
$ git fetch origin master # 將遠端origin的master版本拉下來
#(尚未merge)
$ git pull origin master # git pull = fetch + merge
$ git pull --rebase # pull使用rebase
$ git push -f # --force強迫push
$ git clone url # 複製一份到電腦
參考資料:
Git版控