天天看點

新手入門系列-git執行個體引導

1. 說明

  • 從原理到實際
  • 從場景出發
  • 先本地
  • 在遠端

1.1 概念/原理

  1. git 關心的是“檔案快照”,而非“差異比較”。SVN等關心的是“差異”。簡單了解就是,git每次送出都是完整檔案的儲存。不會比較同一檔案在這次送出有什麼變化。
  2. git 大多數的操作都在“本地”
  3. git 每次commit都是在移動

    HEAD

    HEAD

    相當于指針,指向某次送出
  4. 每個檔案都會有三種狀态:

    未追蹤

    暫存

    已入庫

  5. git 所有指令都是圍繞檔案的狀态,與倉庫的狀态來工作
  6. git 三個地方,對應檔案三種狀态。
    1. Workspace:

      工作區

      ,代碼目錄。包含了所有狀态的檔案
    2. Index / Stage:

      暫存區

      ,git add了但沒有送出的檔案
    3. Repository:

      本地倉庫

      ,git commit入庫後的存儲
    4. Remote:

      遠端倉庫

新手入門系列-git執行個體引導

2. 本地代碼一般操作

2.1 本地代碼庫初始化

  • 進入本地代碼根目錄執行,系統會預設建立"master"分支
    //假設代碼目錄有檔案不需要這一步
    $touch 1.txt
    //初始化git環境
    $git init
               
  • 添加本地檔案到倉庫并送出(兩個指令)。兩個&的含義是,前面一個指令執行出錯,後面的就不會執行。注意: -m 表示本次送出的說明。一定要有
  • 檢視分支,master已經出現并作為預設分支
    $git branch
    * master
               

2.2 建立與檢視本地分支,*号代表目前代碼所在分支

  • 從master作為“父分支”建立本地分支dev。注意繼承關系。從哪個分支建立子分支,代碼就從哪個分支繼承
    $git branch dev
               
  • 切換到本地分支dev
    $git checkout dev
               
  • 檢視本地分支(因為checkout到dev了,是以*号在dev分支上
    $git branch
    * dev
    master
               

2.3 修改代碼并送出到本地分支“dev”

  • 寫入"123"到a.txt,如果a.txt不存在系統會建立
    $echo "123" > a.txt
               
  • 執行status指令,檢視代碼狀态。可以看到提示“要把檔案加入倉庫追蹤”
    $git status
    On branch dev
    Untracked files:
    (use "git add <file>..." to include in what will be committed)
      a.txt
    nothing added to commit but untracked files present (use "git add" to track)
               
  • 根據提示把檔案加入追蹤并送出到本地
  • 再次執行status,提示工作區是幹淨的
    $git status
    On branch dev
    nothing to commit, working directory clean
               

2.4 代碼修改完畢後,合并到master分支

通過2.3我們改變了dev,改動完畢,這時候要合并代碼到master。但在合并到master之前需要先更新master代碼到dev。

目前通行且最佳的方案是采用rebase方案。rebase方案與merge的優劣我們不在這裡讨論,請自行搜尋。

簡單了解就是:rebase使得送出路線更加清晰,而merge會因為“分支”過多,合并過多導緻送出路線雜亂追蹤起來比較難。但rebase會丢失很多送出細節,也不是完美合并。
  1. 總之:非常難單一的使用哪個就能解決所有問題!
  2. 先統一名稱:上遊、下遊
  3. 如果

    dev

    是從

    master

    建立出來的分支。那麼,master就是dev的

    上遊

    ,dev就是master的

    下遊

  4. 下遊合并上遊,要盡可能的保持送出路徑簡潔,那麼采用"Rebase"
  5. 上遊合并下遊代碼,要盡可能的保持送出細節,那麼采用"merge"

想了解更多幫助了解,參考兩篇文章

  • 動畫圖解 Git 指令
  • GIT使用rebase和merge的正确姿勢

2.4.1 實際例子

  1. dev是從master建立的分支
    $git branch dev
    $git checkout dev
               
  2. dev開發一段時間後,master已經被其它同僚修改了一些内容。dev本身也做了一些送出。這時,需要更新master代碼才能做dev的測試。這時候就是:“下遊合并上遊”。那麼采用

    rebase

    $git rebase master
               
  3. dev開發完畢了,這時候需要合并到master。這時候就是:“上遊合并下遊”。那麼采用

    merge

    $git checkout master
    $git merge dev
               

3. 将現有代碼納入管理

3.1 本地代碼從未納入過倉庫,倉庫也是空的

這種最簡單,按照如下執行即可

  1. 設定郵箱,使用者名
    $git config --global user.name "smokelee"
    $git config --global user.email "[email protected]"
               
  2. 進入代碼的根目錄
    //初始化本地代碼倉庫
    $git init 
    //将遠端倉庫主機命名為"origin",并與本地的master建立追蹤關系
    //origin 是遠端主機`本地别名`,名字可以自定義的,不會影響到遠端
    $git remote add origin ssh://gi[email protected]:10022/lihao/gitlearn.git  
    //把本地代碼加入到代碼追蹤
    $git add .
    //把本地代碼送出到本地倉庫
    $git commit -m "Initial commit"
    //推送本地代碼到遠端主機“origin”的"master"
    //git push <遠端主機名> <本地分支名>:<遠端分支名>
    //遠端分支被省略,如上則表示将本地分支推送到與之存在追蹤關系的遠端分支。一般本地與
    //遠端分支會同名
    $git push -u origin master
               

    git push -u

    這個要注意,第一次送出時采用了

    -u

    ,含義是同時設定本地分支“master”與遠端的"origin/master",建立追蹤關系。那麼以後再

    push

    代碼時,直接使用

    git push

    就可以了。

3.2 本地代碼,某個送出錯了,向撤回送出

用git reset 指令實作回退,但怎麼回退是個學問。
  1. 直接扔掉回退間的代碼是一種(Hard)
  2. 回退但保留指定回退間産生代碼是一種(Soft)
  3. 本質是移動git的HEAD指向

3.2.1 先來硬的

何為硬?不管

暫存區

有沒有追蹤但未送出的檔案,不管上次送出改了什麼,通通丢棄。對!就是你了解的丢掉。
  1. 想撤回

    本次送出的上1個送出
    $git reset --hard HEAD^
               
  2. 想撤回

    本次送出的上N個送出
    $git reset --hard HEAD~N
               
  3. 撤回

    某個送出
    $git reset --hard 98abc5a
               
  4. 誤操作怎麼辦?reflog(30天内)
    $git reflog
    b7057a9 HEAD@{0}: reset: moving to b7057a9
    98abc5a HEAD@{1}: commit: more stuff added to foo
               

    98abc5a

    就是被

    掉的送出。
    git reset --hard 98abc5a
               
    再次git log檢視。丢掉的内容回來了!
    $git log 
    98abc5a (HEAD, master) more stuff added to foo
               

3.2.2 再來軟的

何為軟?與硬不同的是,軟隻回退送出,但中間産生的檔案不丢棄!

操作與hard一緻,不做更多說明

4. 連接配接遠端

4.1 從遠端下載下傳代碼,注意:隻會下載下傳

master

代碼

git clone ssh://xxxxxx/xxxx/prj.git
           

4.2 下載下傳後切換到分支

  1. 檢視所有分支
    $git branch -a 
    master
    remotes/origin/HEAD -> origin/master
    remotes/origin/dev
    remotes/origin/master
               
  2. 切換到

    dev

    分支,并建立

    遠端分支

    本地分支

    關聯
    $git checkout -b dev origin/dev
               
  3. 更新遠端分支到本地
    $git pull --rebase
               
    如果沒有走1、2兩步,不要用3。其它後面會講

4.3 本地建立分支,修改,并送出"遠端分支"

前提條件

dev

已經與遠端

origin/dev

建立關聯。請看4.2

  1. dev

    上建立feature分支并修改
    $git branch feature<jira編号>-smokelee-20200423
    $git checkout feature<jira編号>-smokelee-20200423
    $touch newfeature.java 
    $git add . && git commit -m "add feature"
               
  2. 該下班了,還沒改完,送出到遠端伺服器(小變化無需上傳)
    $git push origin feature<jira編号>-smokelee-20200423
               
  3. 第二天修改完了,合并到

    dev

    。先更新

    dev

    $git checkout dev
    $git pull --rebase
               
  4. 合并feature到dev
    $git merge f1
    $git push
               
  5. 合并成功,沒有問題。删除遠端分支
    $git checkout feature<jira編号>-smokelee-20200423
    $git push origin :feature<jira編号>-smokelee-20200423
               

注意5中的第二條指令冒号前是空的,複習:git push <遠端主機名> <本地分支名>:<遠端分支名> 本地分支名不設定,就表示删除遠端分支

4.4 幹拉一個分支到本地

不從任何

本地分支

建立

feature

分支。并且不建立

本地

遠端

分支關聯。

要建立關聯也簡單,git pull後設定

git branch --set-upstream-to=origin/dev feaure-xxx-xxxx

這裡純粹在示範完整用法,就是字打的多點

  1. git pull origin <遠端分支名>:<本地分支名>
    $git pull origin master:feaure-xxx-xxxx
    //關聯遠端與本地分支
    $git branch --set-upstream-to=origin/dev feaure-xxx-xxxx
    $git checkout feaure-xxx-xxxx
               
  2. 修改

    feaure-xxx-xxxx

    并送出
    $touch f1.java
    $git add . && git commit -m "dev1"
               
  3. 修改代碼測試完畢準備送出到

    遠端分支

    $git pull origin dev:feaure-xxx-xxxx --rebase
    $git push origin feaure-xxx-xxxx.local:dev
               
    在關聯了

    遠端

    本地

    分支情況下語句簡單多了。
    $git pull --reabase
    $git push