Try   HackMD

路人起步-邁向前端工程師-從零開始理解Git

Git是什麼

Git是一個是一個免費的、開源的工具,是一個版本控制系統軟體,可以從官網直接下載到本機電腦,它可以幫助軟體開發過程更順暢。Git好比一個管家,我們可以透過Git對程式碼進行分散式的版本修改控制(Git is a free and open source distributed version control system)。

為什麼要使用Git

  • 備份管理好輕鬆
    一個功能/軟體/網站/App的開發過程,需要管理不同階段的程式碼修改,沒有Git以前,我們得拷貝數個檔案、用日期命名、新增拷貝一堆資料夾在自己的電腦上備份,再一一上傳到遠端料庫更新,有時還要擔心上傳的檔案會不小心與協作夥伴彼此覆蓋。

  • 管家幫你監視倉庫
    Git就像是一個管家,我們把所有專案開發的程式碼放在一個倉庫中,在這個倉庫內所發生的所有繁雜修改過程,都可以託管給這個管家,命令它隨時檢視、回報異動等等,再由Git幫我們跑腿,把這個倉庫內產生的所有紀錄,傳送到另一個遠端的倉庫。

  • 回心轉意改到好
    傳送到遠端的好處是當我們發展程式碼到某個階段,有時候發現行不通覺得以前寫得更好時,我們可以請Git幫我們從遠端的倉庫(Remote Repository)召喚回來某個節點當時的狀態紀錄,再從這個指定狀態持續發展。

  • 本地倉庫與遠端倉庫
    除此之外,我有我的倉庫,我的同事也會有他的倉庫,如果我們兩邊傳送到遠端的東西重疊了,例如:兩個檔名相同但是內容有差異的檔案,也就是發生衝突,Git管家也會警示,等待我和同事判斷處理方式後(例如:兩者合併後皆保留或是只留其一),才會真正送入遠端數據庫,就不會搞不清楚遠端數據庫的資料到底是誰的或是哪個才是最新版。

Git管家會紀錄所有的更動,讓合作夥伴能知道每次程式碼修改的原因與位置,團隊協作起來更省事。

Git 和 Github的差別

Git不是Github

  • Git是一個軟體,可以進行版本控制;
  • Github是一個網站空間,可作為遠端數據庫,提供程式碼上傳代管。
  • Git 和 Github有連結,是因為我們主動指定把本機上的檔案傳送到Github空間上,他們的關係才生效的。

我們可以把本機端數據庫(Local Repository)中的檔案,透過Git這個工具上傳到Github這個遠端數據庫(Remote Repository)上備份與紀錄。(得先給Github一把公鑰,讓它認識你的電腦是哪一台)

簡單來說,我本機上有一個專案倉庫,在Github上我建立了另一個名稱相同的倉庫,我透過Git這個工具,讓檔案在兩者之間傳輸。

Git的安裝與資料夾初始化:建立本機倉庫並邀請管家進駐

You can take a local ==
== that is currently not under version control, and turn it into a Git repository.

  1. 官方網站下載軟體
  2. 使用Command Line的方式,在本機上任意位置新增一個資料夾,並命名為hello_git
mkdir hello_git
  1. 要讓這個普通的資料夾hello_git成為專案倉庫,需要對他進行git的初始化。於hello_git的路徑之下,輸入
git init

初始化的目的是讓 Git 開始對這個資料夾進行版本控制,也就是邀請Git管家進入管理這個倉庫。

  1. 輸入ls -a 查看hello_git是否已經有.git隱藏資料夾的進駐

看到.git的存在就表示這個資料夾已經初始化成功,此時hello_git再也不是一個普通的靜態資料夾,它現在同時擁有三個狀態:

  • 工作目錄(Working Directory)
  • 索引清單待命區(Staging Area)
  • 本地數據庫(Local Repository)
  1. 辨識預設的主線:main
    與此同時,在Command Line軟體介面中會看到hello_git路徑名稱後方多了(main)標籤,表示hello_git初始化的同時,也預設產生了一個名為main的主要branch(分支)。

分支(branch)是什麼
main這個branch好比一個專案的主線任務。同一個Repository中可以有多個branch,也就是除了主線,還可以存在多個支線任務。

例如:開發一個購物網站,中途需要研發測試3個新功能/修改,所以從主線身上開了3個分支,各自命名為:signIn_button、fav_list、price_tag,
最後只採用price_tag的分支要正式上線,
此時就可以只把price_tag合併到main之中。(把小分支合併到主線分支)

主線branch其實不一定得叫做main,你也可以把它改成任何其他名稱,只是main這個名稱是預設的而且很直覺理解。

預設的branch名稱以前叫做master,但是自2020開始10月新Git儲存庫的預設命名,以main來取代原本的master。

取得SSH金鑰並上傳到GitHub讓它認識你的電腦

  1. 先去Github上註冊一個新的帳號
  2. 在Github上新增一個名稱與本機相同的公開Repository
  3. SSH Key有兩種:公鑰與私鑰。公鑰要丟上去給GitHub讓它認識我們的電腦,私鑰留在本機中。
  4. 在Mac環境中,進入根目錄之下的.ssh資料夾中(如果沒有就自己新增一個)
cd ~/ .ssh

  1. 輸入以下指令取得SSH Key,雙引號內的email要輸入當初註冊Github的同一個
ssh-keygen -t rsa -C"your_email@youremail.com"
  1. 產生完畢後資料夾內會產生id_rsaid_rsa.pub兩個檔案,有.pub的是公鑰,使用cat指令取得公鑰內容並複製貼到Github上
cat id_rsa.pub
  1. 到Github>Settings>SSH keys 頁面中,點選「New SSH key」輸入title,並把剛才複製的公鑰內容貼上,再按「add SSH Key」

將Github指定為遠端數據庫

由於我們已經在本機上新增過一個本地Repository,現在需要將本地Push給遠端的Github。

回到剛才在Github開創的Repository上,點選「code」頁籤,點選「SSH」,此時會Github會自動顯示出類似網址的東西。依照Github頁面上的 …or push an existing repository from the command line之下,複製相對應的指令貼到終端機上,就能完成本機Loca Repository和Github遠端Remote Repository的連結。讓兩個倉庫相通了。

Branch新增

先新增一個名為dev的新Branch

git branch dev

Branch的切換

  1. 使用git checkout 指令從main切換至devbranch
git checkout dev
  1. 在main branch 和 dev branch 各新增數個檔案且以便比較兩者狀態差異
  • main:I am master.md、hello.txt、hi.txt

  • dev :hello_branch.md、hello.txt、hi.txt

  • 將新增異動commit至Local Repository,給予描述讓人知道異動的意義

git commit -m "有意義的描述文字"

無論是main還是dev都是在hello-git資料夾路徑內,但是當branch切換時,路徑內的檔案也會跟著切換。可以觀察到圖形介面在分支切換時會閃爍一下:

Branch的衝突與合併

假如不同分支中出現「相同檔名但是內容不同的檔案」,要把分支合併為一條時,Git會因為不曉得該保留誰與內容取捨,而出現衝突。

  • mainbranch中也新增一個hello_branch.md,並在檔案內輸入「main's hello branch」等文字內容。而devbranch中的hello_branch.md內中的文字則是「dev's hello branch」。兩者不同內文以作區分。
  • 將這次的檔案新增添加至 staging area 中
git add hello_branch.md
  • 將異動添加至Local Repository並給予描述
git commit -m "add hello_branch.md to main"
  • 現在兩條分支各擁有的檔案如下:

【main】

    • i am master.md
    • hello_branch.md
    • hello.txt
    • hi.txt

【dev】

    • hello_branch.md
    • hello.txt
    • hi.txt

比較可發現,i am master.md 只有main分支有所以合併不會有衝突,而hello.txthi.txt因為內容相同,所以合併時也不會有取捨問題的衝突,但是hello_branch.md不僅兩邊的分支都有出現,同名但是檔案內容不同,這樣在分支合併時就會出現取捨衝突。

  • 在main分支下,使用git merge dev 試圖將dev分支合併至main中會出現衝突警告。

  • git status檢查,顯示因為兩邊都有「hello_branch.md」所以未合併。所以我們要先解決檔案內容不一致的狀態。

  • 使用VS code 開啟hello_branch.md比對兩個同名檔案內容差異之處並修正。這次的做法是把兩個檔案內原本的內文都註解掉,並打上新的文字儲存,讓檔案內容整合在一起。

  • 修改完後hello_branch.md內容後,一樣要把異動add至索引清單
git add hello_branch.md
  • 使用git status再去查看就會發現檔名變成綠色字

  • 再次執行commit讓合併生效
commit -m "merge dev branch"

名詞清單

  • repository:數據庫
  • main:本地數據庫(logcal repo)main是預設別名
  • origin:遠端數據庫 (remote repo)origin是預設別名
  • git init:讓Git對資料夾進行初始化
  • git status:查看狀態,檢查是否有任何待辦事項或是衝突
  • git add:將檔案加入索引清單。從此檔案中只要有任何修改都會被git追蹤(track)。

如果在工作目錄(Working Directory)新增一個檔案,但沒有加到索引清單內,用git status檢查,會列出紅字的檔名,表示此檔案存在但是未被追蹤。直到使用git add將檔案加入代辦索引清單之後,再次git status檢查狀態,檔名便會顯示為綠字,表示已被追蹤。

  • git commit -m "字串":將目前所做的改變加至本地數據庫(Local Repository)且字串中可輸入任何文字用以說明異動原因。

  • git log:查看目前為止所有的動作紀錄

  • git branch <name>:新增一個指定名稱的新branch。

例如:git branch dev 就是新增一個名為dev的branch

  • git branch:列出所有branch。

前面有*者表示是目前所屬Branch

  • git checkout <branch名稱>:切換至指定名稱的branch