git 實作練習 1

@ver 0.1.2 @date 2019-02-26 12:38:11 (星期二)

@ver 0.1.1 @date 2019-02-18 08:07:05 (星期一)

萬物皆可 git

git 是文件版本管理系統, 它不僅僅是管理文字格式的程式碼, 包括非文字格式的二元檔案, 例如圖片 jpg, png 或文件 word, excel, ppt ... 等 binary 檔案, 都可以利用 git 搭配各種文件解析 plugin 程式, 進行文件檔案的版本追踪控制及管理.

每一次提交到倉庫, 相當於把現有文件做一次快照 (snapshot) , git 用各種方式把差異, 記錄在 .git 倉庫裡. 所以在某一個時刻想查看曾經某一個當下提交的程式碼時, 便可立即搭時光機還原返回那一個時間點的版本. 當然, 既然穿越到過去, 也得回到未來. 下一道指令, 就從過去那個版本, 再回到正在傷腦筋的現在這一刻.

[alex@nvda /tmp/prj1 ]$ git --version
git version 2.11.0
[alex@nvda /tmp/prj1 ]$

以下請大家跟著我一邊實作基本操作, 同時講解對應的各種 git 功能, 下列是此次會用到的命令

git config
git init
git status
git status -s
git add {filename}
git add .
git commit -m '記錄一下此次提交修改的相關訊息'
git log

注意 :

大家可以在 /tmp 下實作, 或在自己的 /home/ooo/ 目錄下, 如果在 /tmp 之下, 記得要使用不同名稱的專案子目錄.

在執行結果裡, 會有 # 標記, 此標記之後代表說明

  1. git config 設定基本識別資料

    安裝 apt install git 之後

    首次使用 git 要先設定基本識別資料, 這很重要, 因為每次提交會把這些基本識別資料加入倉庫, 而且提交後不能再修改, 除此之外, 設定檔裡面還有許多設定會讓你更方便使用命令列來操作 git .

    基本資料設定檔預設是個人 home 目錄下的 ~/.gitconfig, 因為每個人用自己的帳號登入之後, 便以此為準. 但也可以放在專案目錄之下, 至於為何需要如此設置, 後續再研究.

    命令

    ll ~/.gitconfig

    執行結果

    [alex@nvda ~ ]$ ll ~/.gitconfig
    ls: 無法存取 '/home/alex/.gitconfig': 沒有此一檔案或目錄
    [alex@nvda ~ ]$

    因為剛開始使用 git, 現在 .gitconfig 還沒產生, 所以找不到此檔案


    建立自己的姓名及郵件, 切記要加 --global, 設定檔才會是在 ~/.gitconfig, 否則會放在現在目錄之下

    命令

    git config --global user.name alex                      # 請輸入自己的姓名, 建議用英文字母, 聽說中文會有一些問題
    git config --global user.email alex@forblind.org.tw     # 請輸入自己的電子郵件信箱

    執行結果

    [alex@nvda ~ ]$ git config --global user.name alex
    [alex@nvda ~ ]$ git config --global user.email alex@forblind.org.tw

    查看 config 設定

    命令

    git config --list
    cat ~/.gitconfig

    執行結果

    [alex@nvda ~ ]$ git config --list
    user.name=alex
    user.email=alex@forblind.org.tw
    [alex@nvda ~ ]$ cat ~/.gitconfig
    [user]
            name = alex
            email = alex@forblind.org.tw
    [alex@nvda ~ ]$

    參考 : 其它有用的設定

    git config --global alias.co checkout
    git config --global alias.br branch
    git config --global alias.st status
    git config --global alias.l "log --oneline --graph"
    git config --global alias.ls 'log --graph --pretty=format:"%%h <%%an> %%ar %%s"'
    git config --global core.editor emacs

    我們先加上一個好用的 alias

    命令

    git config --global alias.st status
    git config --list

    執行結果

    [alex@nvda ~ ]$ git config --global alias.st status
    [alex@nvda ~ ]$ git config --list
    user.name=alex
    user.email=alex@forblind.org.tw
    alias.st=status
  2. 建立專案

    首先我們要先建立專案子目錄, 在此目錄之下的所有檔案, 都會被 git 索引追踪管理, 除非在 .gitignore 把它排除忽略 (例如 : *.bak)

    命令

    cd /tmp
    mkdir prj1
    cd prj1
    ls -a

    執行結果

    [alex@nvda /tmp ]$ cd /tmp          # 先進入 /tmp
    [alex@nvda /tmp ]$ mkdir prj1       # 專案子目錄名
    [alex@nvda /tmp ]$ cd prj1          # 再進入專案子目錄
    [alex@nvda /tmp/prj1 ]$             # 完成
    [alex@nvda /tmp/prj1 ]$ ls -a       # 檢視現有專案子目錄的檔案
    .  ..
    [alex@nvda /tmp/prj1 ]$
  3. git init 初始本地倉庫 Repository

    git 初始化的目的是要讓 git 開始對這個目錄(含各層級的子目錄)下的所有文件進行版本控制, 所以每個專案只要做一次即可

    命令

    git init
    ls -a

    執行結果

    [alex@nvda /tmp/prj1 ]$ git init
    Initialized empty Git repository in /tmp/prj1/.git/         # 出現此行文字, 表示初始化完成
    [alex@nvda /tmp/prj1 ]$ ls -a
    .  ..  .git                                                 # 檢查會發現多了一個 .git 的子目錄, 這個是本地倉庫的所在地
    [alex@nvda /tmp/prj1 ]$
  4. 短短的幾行程式碼

    現在先寫幾個簡單的程式碼及文件檔案, 分散在幾個不同的子目錄裡

    命令

    vi index.php
    vi README.md
    ls -a

    index.php 程式碼如下 :

    <?php
    echo 'hello, world. Version 1';
    echo '這是我們的第一個版本';
    ?>

    命令

    vi README.md

    README.md 說明檔如下 :

    這是我們的第一個版本的說明檔
    
    現在時間是 2019-02-19 15:14:43 (星期二)

    執行結果

    [alex@nvda /tmp/prj1 ]$ ls -a
    .  ..  .git  index.php  README.md                   # 剛剛新建的兩個檔案 index.php  README.md
    [alex@nvda /tmp/prj1 ]$
  5. git status 觀察檔案的變化

    第二個接觸到的 git 命令是 git status, 列出此專案檔案變化的相關資訊

    命令

    git status

    執行結果

    [alex@nvda /tmp/prj1 ]$ git status
    On branch master
    
    Initial commit
    
    Untracked files:
      (use "git add <file>..." to include in what will be committed)
    
            README.md
            index.php
    
    nothing added to commit but untracked files present (use "git add" to track)
    [alex@nvda /tmp/prj1 ]$ 

    關於檔案狀態

    注意看 Untracked files: 這一行之下的幾個檔名, 都是剛新增的檔案. Untracked 的 意思是『尚未被 git 索引追踪』.

    git status 執行結果, 可能還會有另兩種提示

    如果是 Changes not staged for commit: 表示這個檔案『先前已被 git 索引追踪, 但修改內容後, 沒有用 git add 告知我們要在這次的提交中更新其狀態』.

    如果是 Changes to be committed: 表示這些檔案『已被 git 索引追踪, 而且已使用 git add 告知狀態更改』, 也就是進入暫存區(索引). 檔名前面還會再加上三種不同的指示

    • deleted: 表示此檔案被刪除
    • modified: 表示檔案內容有更動
    • new file: 表示為此次提交要新增追踪的檔案

    檔案狀態的三種不同提示 :

    • {#MY-LIST-ID .my-list-type-disc start=1 type=A} Untracked files:
      從上次提交後, 在工作目錄下新建立的檔案, 尚未被 git 索引追踪
    • Changes not staged for commit:
      檔案在先前已被 git 索引追踪, 但修改內容後, 沒有用 git add 告知要在這次的提交中更新其狀態
    • Changes to be committed:
      檔案在先前已被 git 索引追踪, 而且已使用 git add 告知狀態更改

    後面兩種 Changes 開頭的提示, 在每一個檔案名稱前, 可能有下列三種標示 :

    1. deleted: 表示此檔案被刪除
    2. modified: 檔案內容有修改過
    3. new file: 新加入索引追踪的檔案
  6. 觀察檔案的變化之短格式

    現在在命令末尾加上 -s , 它的意思是 Short Format 短格式

    因為先前有指定 alias, git config --global alias.st status 所以 git st -s 等同 git status -s 命令, 以後會全部使用 git st 來操作

    命令

    git status -s
    git st -s

    執行結果

    [alex@nvda /tmp/prj1 ]$ git status -s           # Short Format 短格式
    ?? README.md
    ?? index.php
    [alex@nvda /tmp/prj1 ]$ git st -s               # alias 用法的 Short Format 短格式
    ?? README.md
    ?? index.php
    [alex@nvda /tmp/prj1 ]$ 

    跟先前顯示出來的方式有點不同, 也簡短了許多, 最前面兩碼 ?? 雙字母狀態碼, 表示 Untracked 未被索引追踪

    雙字母狀態碼可能會有下列七種字元

    * ' '  = 未修改 (空白)
    * M = 修改
    * A = 已添加
    * D = 刪除
    * R = 重命名
    * C = 複製
    * U = 更新但未被合併

    X shows the status of the index. 暫存區(索引)的狀態

    Y shows the status of the work tree. 工作目錄的狀態

    以下的 "被索引追踪", 也就是說曾經 git add 過此檔案, 在那個當下的文件會放入暫存區(索引)

    X 第一碼
    暫存區(索引)的狀態
    Y 第二碼
    工作目錄的狀態
    中文說明 英文說明
    ? ? 未被索引追踪 untracked
    ! ! 忽略此檔案(要搭配參數 --ignored, 才會顯示) ignored
    ------- ------- ----------------- --------------------------
    A ' ' 新檔案, 被索引追踪, 尚未提交 added to index
    A M 新檔案, 被索引追踪, 尚未提交, 但工作目錄下的檔案內容有修改異動 added to index, modified
    A D 新檔案, 被索引追踪, 尚未提交, 但工作目錄下的檔案已改檔名或被刪除 added to index, deleted or renamed
    ' ' M 已被索引追踪, 尚未更新到暫存區(索引), 但工作目錄下的檔案有修改異動 not updated, modified
    ' ' D 已被索引追踪, 尚未更新到暫存區(索引), 但工作目錄下的檔案已改檔名或被刪除 not updated, deleted
    M ' ' 工作目錄下的檔案有修改異動, 被加入索引追踪, 尚未提交 TBD
    M M TBD TBD
    M D TBD TBD
    D ' ' TBD TBD
    D M TBD TBD
    R ' ' 在暫存區(索引)中重新命名, 被索引追踪, 尚未提交 renamed in index, modified
    R M 在暫存區(索引)中重新命名, 且工作目錄下的檔案有修改異動 renamed in index, modified
    R D TBD TBD
    C ' ' TBD TBD
    C M TBD TBD
    C D TBD TBD
    ------- ------- ----------------- --------------------------
    ' ' [MD] 已被索引追踪, 但未更新到暫存區(索引) not updated
    M [ MD] git add 之後, 更新到暫存區(索引) updated in index
    A [ MD] 已添加到暫存區(索引) added to index
    D [ M] 從暫存區(索引)中刪除 deleted from index
    R [ MD] 在暫存區(索引)中重新命名 renamed in index
    C [ MD] 複製到暫存區(索引)中 copied in index
    [MARC] ' ' 暫存區(索引)和工作目錄匹配 index and work tree matches
    [ MARC] M 工作目錄自暫存區(索引)以來發生了變化 work tree changed since index
    [ MARC] D 在工作目錄中被刪除 deleted in work tree
    ------- ------- ----------------- --------------------------
    D D 未被合併, 全都被刪除 unmerged, both deleted
    A U 未被合併, 由我們添加 unmerged, added by us
    U D 未被合併, 被他們刪除 unmerged, deleted by them
    U A 未被合併, 由他們添加 unmerged, added by them
    D U 未被合併, 被我們刪除 unmerged, deleted by us
    A A 未被合併, 全都被添加 unmerged, both added
    U U 未被合併, 全都已修改 unmerged, both modified
  7. 把檔案交給 git 管理

    (use "git add" to track) 這是上一節 git status 命令的最後一句話.

    命令

    git add

    執行結果

    [alex@nvda /tmp/prj1 ]$ git add
    Nothing specified, nothing added.
    Maybe you wanted to say 'git add .'?
    [alex@nvda /tmp/prj1 ]$
    
    原文照翻 : 沒有指定任何東東, 所以沒有加入索引追踪. 也許你要下的命令是 `git add .`

    照它指示下命令, git add 就是把新的未索引追踪檔案加入到暫存區

    命令

    git add .

    執行結果

    [alex@nvda /tmp/prj1 ]$ git add .

    注意 : git add . 沒有任何回應, 這表示, 一切正常

    再度觀察檔案的變化

    命令

    git status
    git status -s

    執行結果

    [alex@nvda /tmp/prj1 ]$ git status
    On branch master
    
    Initial commit
    
    Changes to be committed:
      (use "git rm --cached <file>..." to unstage)
    
            new file:   README.md
            new file:   index.php
    
    [alex@nvda /tmp/prj1 ]$ git status -s
    A  README.md
    A  index.php
    [alex@nvda /tmp/prj1 ]$ 

    new file: 或最前面兩碼 "A ", 表示此檔案已添加到暫存區(索引), 加入 git 索引追踪為新檔案

  8. git commit 最後一哩路

    commit 提交到 repo, 才算完成整個 git 版本管理流程

    命令

    git commit -m '第一次提交到 git repo'

    執行結果

    [alex@nvda /tmp/prj1 ]$ git commit -m '第一次提交到 git repo'
    [master (root-commit) f2ed5d7] 第一次提交到 git repo
     2 files changed, 6 insertions(+)
     create mode 100644 README.md
     create mode 100644 index.php
    [alex@nvda /tmp/prj1 ]$ 

    看到這些訊息, 代表完成此階段的提交

    再度觀察檔案的變化

    命令

    git status
    git status -s
    git st
    git st -s

    執行結果

    [alex@nvda /tmp/prj1 ]$ git status
    On branch master
    nothing to commit, working tree clean
    [alex@nvda /tmp/prj1 ]$ git status -s
    [alex@nvda /tmp/prj1 ]$ git st
    On branch master
    nothing to commit, working tree clean
    [alex@nvda /tmp/prj1 ]$ git st -s
    [alex@nvda /tmp/prj1 ]$

    沒東東...所以...OK啦

  9. git log 看看提交後的訊息

    命令

    git log
    git log --stat
    git log --pretty=format:"%h - %an, %ar : %s"

    執行結果

    [alex@nvda /tmp/prj1 ]$ git log
          1 commit f2ed5d757c9a81de0d1ccd601af1e4a6a48333e4
          2 Author: alex <alex@forblind.org.tw>
          3 Date:   Tue Feb 19 16:24:19 2019 +0800
          4
          5     第一次提交到 git repo
    (END)
    要按 Q 鍵離開此檢視畫面
    
    [alex@nvda /tmp/prj1 ]$ git log --stat
          1 commit f2ed5d757c9a81de0d1ccd601af1e4a6a48333e4
          2 Author: alex <alex@forblind.org.tw>
          3 Date:   Tue Feb 19 16:24:19 2019 +0800
          4
          5     第一次提交到 git repo
          6
          7  README.md | 2 ++
          8  index.php | 4 ++++
          9  2 files changed, 6 insertions(+)
    [alex@nvda /tmp/prj1 ]$ git log --pretty=format:"%h - %an, %ar : %s"
          1 f2ed5d7 - alex, 14 minutes ago : 第一次提交到 git repo
    (END)
    [alex@nvda /tmp/prj1 ]$ git log --oneline
          1 f2ed5d7 第一次提交到 git repo
    [alex@nvda /tmp/prj1 ]$

    等後面有很多次提交, 再來討論 git log 的應用

  10. 本章總結

    本章使用 git 命令總結

    git config                          # 設定基本識別資料
    git init                            # 初始化, 在這個專案之下, 建立 .git 這個子目錄及裡面的相關結構, 所以每個專案只要做一次即可
    git status                          # 觀察檔案的變化
    git status -s                       # 觀察檔案的變化之短格式
    git st                              # git alias 觀察檔案的變化
    git st -s                           # git alias 觀察檔案的變化之短格式
    git add <filename>                  # 將此路徑檔案加入暫存區(索引)
    git add .                           # 將所有檔案加入暫存區(索引)
    git commit -m 'message'             # 暫存區(索引)提交至倉庫, 包含提交訊息
    git log                             # 顯示提交的結果及訊息
    git log --stat                      # 顯示提交的結果及訊息
    git log --pretty=format:"%h - %an, %ar : %s"  # 顯示提交的結果及訊息