git 介紹
git是一個版本控制的軟體,今天在開發一個程式或專案的時候,一定不是馬上就寫出來,是經過很多次的修改才完成的,而git就是一個方便管理這些版本、在這些版本移動、合併不同版本的軟體
github 介紹
github是一個給大家放 git repository的地方,repository是儲存庫的意思,通常大家會直接說repo,因為git是一個管理版本的軟體,repo就是用來儲存不同版本的地方。
今天如果要開發一個東西,就要先開一個git repo,在那個git repo裡面做事,git才會幫我們管理這些版本
github就是一個可以放repo的地方(github是個網站),有點類似雲端硬碟,但上面就只能放git repo,把repo放在github上,就可以透過網路在其他地方下載你要的檔案(clone)。多人開發專案的時候,可以透過把修改的部份推上去github(push),再讓其他人拉下來(pull),他就可以有你開發的部份了。
安裝git
For window users: download git bash
For macOS users: 可以直接在terminal打git指令,如果系統發現你還沒安裝過,便會自動提示你安裝
For linux users: sudo apt-get install git-all
git 基礎
git操作最基本會牽涉到四個地方: Working Directory, Staging Area, Local Repository, Remote Repository
- Working Directory: 你在使用的資料夾,可以想成是你的工作臺
- Staging Area: 在repo跟Directory之間的一個暫存空間,有點像是把一個工作臺完成的貨物送往倉庫的卡車
- Local Repository: 儲存各個版本的地方,可以想成是你的大倉庫
- Remote Repository: 儲存各個版本的地方,只是他在遠端(ex: github),可以想成是你的遠端大倉庫
最基本的git操作大概會是這樣的流程
- 在Working Directory編輯修改一些檔案
- 用add指令,將他們放上送往repo的卡車(Staging Area)
- 用commit指令,卡車就會出發,把上面的資料送進倉庫(Local Repository)
像這樣子整個步驟做完,repo就會多出一個commit,相反的,也可以把東西從倉庫拿回工作臺,把commit送進去之後,如果想回到特定的某一次版本,可以透過checkout指令,切換到特定的"commit"或是"branch"找到特定版本,git會從Local Repository把當時的檔案叫回Working Directory
基本指令(本地端操作)
基本設定 git config
開始之前,要設定git config
$ git config --global user.name "你的名字"
$ git config --global user.email "你的信箱"
創建git repo(git init)
使用git init
之後,可以在當前目錄創一個repo
實際上它會為當前目錄創一個.git檔(裡面紀錄這個git repo的資料),接下來就可以在這個資料夾底下使用各種git指令
如果在後面多加一個參數 "資料夾名稱",它會把那個名字的資料夾創出來,順便在裡面init一個repo
$ git init
$ git init dir_name
把檔案add到Staging Area git add (檔案)
當新增某個檔案、修改某個檔案內容時,要先將這些檔案用git add
指令把它加入到Staging Area(待提交的名單),在這之後才可以用commit指令把它提交到repo
$ git add path/to/the/file
$ git add .
$ git add --all
清除Staging Area的內容 git reset
可以用這個指令來清掉暫存區的內容,git reset可以接指定檔案,就只把那個檔案從staging area清掉
$ git reset
$ git reset path/to/the/file
(還有另一個清掉add檔案的方式是git rm --cached path/to/file
,但比較接近把repo的該檔案刪除)
提交Staging Area的內容 git commit
把現在的狀態commit成一個快照存到repo裡面(快照就像是把現在的狀態拍張照,然後下次回來這一個commit的時候,就可以讓所有檔案全部回到這張照片的樣子)
使用git commit
之後,預設的編輯器會跑出來,請你填commit message(讓你紀錄這次的commit做了什麼)
如果不想要進入編輯器,可以直接git commit -m "commit message"
如果想要讓這一次的commit直接跟上一次的commit包在一起(可能是補了一些應該要放在上一次commit的東西時),可以使用參數 --amend,會把新的東西跟舊的東西一起打包
$ git commit
$ git commit -m "commit message"
$ git commit --amend
查詢Staging Area狀態 git status
可以用status查看現在的狀態
$ git status
查詢commit紀錄 git log
可以透過git log看到以前的紀錄,會顯示每一筆的commit message跟哪些檔案被新增修改,還有每一個commit的hash value,想要顯示詳細一點可以用參數 --stat,或是用參數 --p
$ git log
$ git log --stat
$ git log --p
切換到某一個commit或branch git checkout(<commit>|<branch>)
每一個commit會有一個hash值,可以寫git checkout hash值
,就可以回到那一次的樣子,但回到過去的只有head,整個main還是在後面那樣,所以如果在這個過去commit了,就會開出一條新的分支
$ git checkout hash
$ git checkout main
.gitignore
有時候我們會希望某些檔案不要被add到Staging Area,這時候可以在建立git repo的資料夾新增一個叫.gitignore的檔案,並寫上想要忽略的檔案名單,之後所有add都會忽略列在.gitignore裡的那些檔案
# 忽略 secret.yml
secret.yml
# 忽略所有副檔名是.exe
*.exe
# 忽略.vscode/ 底下的檔案
.vscode/
這樣符合名單的檔案就會被忽略,git status
也不會把他們列出來,如果真的想要把他們add進去,要用git add -f 檔案名稱
基本指令(與遠端互動)
複製遠端repo到本地端 git clone <repo>
把遠端一個repo,clone到本地端
上傳本機資料到遠端 git push [remote] [branch]
對於已經從遠端clone到本地端的repo,可以把本地端新的資料push上去到遠端,後面可以填要對哪一個remote,push上去哪一個branch(因為可以設很多個remote端,但預設會是最近一次的那個remote)
獲取遠端資料並合併到本機 git pull [remote] [branch]
對於已經從遠端clone到本地端的repo,可以把遠端新的資料pull下來到本地端,跟push一樣,後面可以填要從哪一個remote,pull哪一個branch下來
git 進階
分支的概念
因為git是一個可以讓多人同時合作進行專案的系統,所以為了讓所有人都能不受別人影響製作自己的檔案,因此git提供了branch這個功能
創建repo時,git會自動創造一個main分支,而每個branch都會有一個指標,用來紀錄branch最新的一個commit,每次commit就是把一筆新的資料存入repo,會紀錄下現在資料夾內檔案的狀態,而是在哪個branch上commit,那個branch的指標就會指到這個最新的commit,要將檔案統一時,只要將所有branch合併起來就完成了
查看分支git branch
$ git branch
* master
前面有星星代表所在的分支,如果只要看自己現在在哪個分支,用git status
也可以
新增分支 git branch
$ git branch new_branch
這樣就創造了一個新的branch叫new_branch,他的指標會和現在所在branch指向相同的commit
- 在git裡面有一個特殊的名字叫head,代表你現在所在的地方,所以分支名字記得不要叫head
切換分支 git checkout
$ git checkout new_branch
Switched to branch 'new_branch'
同時新增和切換分支 git checkout -b
$ git checkout -b another_branch
Switched to a new branch 'another_branch'
可以一次完成新建和切換分支
合併分支 git merge
$ git checkout main
Switched to branch 'main'
$ git merge another_branch
Updating 790da90..c730450
Fast-forward
somefile | 2+-
1 file changed, 1 insertion(+), 1 deletion(-)
代表已經把another_branch合併到main這個branch裡面了,一定要先切換到要merge別人的branch上
Fast-forward代表合併的兩個branch是一前一後的關係,並不存在分歧(當前的這個branch在新的branch分裂出去之後沒有其他的commit),那git就會直接將當前這個branch的指標向前拉到有變動的branch的指標的位置
Merge其實是把要被merge的branch(another_branch)上的那些修改重新在當前的branch(main)再做一次,但有時候兩個不同branch都分別更動了同一個檔案,且更動內容不一樣的時候,如果git能夠自行處理哪些需要被留著(兩個branch改的是不同區塊),那最好,但如果同一個區塊同時被兩個branch改到的時候,就要手動recover了
刪除分支git branch -d
$ git branch -d another_branch
Deleted branch another_branch(was 3s08a2j)
和新增branch一樣是用git branch
指令,只是要加上-d或-D,-d只會刪除已經push且被merge掉的branch,-D可以強制刪除branch,不管它有沒有push或被merge
Github
設定帳號的SSH KEY:
- 在terminal上輸入
ssh-keygen
產生ssh key - 複製公鑰(id_rsa.pub)
- 用瀏覽器登入github,進入帳戶設定裡的ssh設定
- 選擇New ssh key,把剛剛複製的公鑰貼在key的欄位
將本地端repo更新上github git remote add
和git push
一開始按github的新增repo的時候,上面的repo會是完全空的,可以在repo頁面找到Quick setup,選擇ssh並複製旁邊的URL,複製完便可使用以下的指令
$ cd local_dir
$ git remote add origin [repo_url]
$ git push -u origin main
其他指令
git diff
: 比較兩個commit的不同之處git show
: 顯示某個commit的內容git reset
: 回復到某個commit的內容git reflog
: 回復到某個head指向的commit變更時的內容git stash
: 把做的修改儲存起來git fetch
: pull = fetch + mergegit rebase
: 另一種merge的方式,把另一個branch的commit一個一個apply到當前的branch上git cherry-pick
: 把某些特定的commit撿到當前的branch上git gc
: 當git專案過於龐大的時候可以刪減一些用不到的資訊