# Outline
一、前言
二、Git CLI
三、Git GUI Tools
A、待敘項目
# TL;DR
通常我們透過 `git init` 去初始化一個 Git 倉庫,它會在專案目錄下產生一個 `.git` 目錄。儘管該目錄有不少子目錄和檔案,但一個被認可的 Git 倉庫,在 `.git` 目錄下只要有擁有 `objects` 和 `refs` 空目錄、以及一個記錄著 `ref: refs/heads/master` 的文字檔 `HEAD` 即可。
# Updated
2019-10-06: 更新標題與文章結構
在雙十連假前,此系列文每天的發文時都會以最簡陳述為主,以求在繁忙的日常中,至少能先維持挑戰鐵人賽的進度,並且逐漸拓展思路與系列結構。預期會在國慶連假將本篇文章論述完整。
平時我們都知道可以透過 git init
去將一個專案 git 化,變成一個被 Git 追蹤、版本控制的專案。那到底 git init
後會發生什麼事呢?這就是今天要來談的內容。
# Command Synopsis: git-init
git init [--options] [directory]
在下面的範例裡,我們新增一個目錄,並透過 ls -al
查看該目錄在執行 git init
前後是有什麼差異。
# Location: ~
$ mkdir how-git-works-lab
$ cd how-git-works-lab
# Location: ~/how-git-works-lab
$ ls -Al
$ git init
Initialized empty Git repository in /Users/ironman/how-git-works-lab/.git/
$ ls -Al
drwxr-xr-x 9 ironman staff 288 9 19 23:07 .git
在這裡,我們發現多了一個 .git
目錄。這就是 Git 用來儲存所以版本歷史、變動、分支、標籤、等等資訊的地方。
在下面的範例中,我們透過用來查詢當前檔案變動狀態的指令 git status
去驗證現在是否是一個被 Git 所追蹤的專案。並且嘗試在刪除 .git
後再執行驗證,去看會有什麼變化。
# Location: ~/how-git-works-lab
$ git status
On branch master
No commits yet
# Delete `.git` directory
$ rm -rf .git
$ git status
fatal: not a git repository (or any of the parent directories): .git
實驗過後,我們發現在刪除 .git
目錄後,再次下 git status
指令後,就會顯示 fatal: not a git repository
的錯誤,表示所在目錄與其父目錄都不是 Git 倉庫(repository)。
.git
Directory透過下面的範例中,我們可以得知 .git
裡面的目錄結構:
$ ls -Al .git
-rw-r--r-- 1 ironman staff 23B 9 19 23:33 HEAD
-rw-r--r-- 1 ironman staff 137B 9 19 23:33 config
-rw-r--r-- 1 ironman staff 73B 9 19 23:33 description
drwxr-xr-x 13 ironman staff 416B 9 19 23:33 hooks
drwxr-xr-x 3 ironman staff 96B 9 19 23:33 info
drwxr-xr-x 4 ironman staff 128B 9 19 23:33 objects
drwxr-xr-x 4 ironman staff 128B 9 19 23:33 refs
用一個文字圖來繪製其樹狀結構大致如此:
# [Repo] dot-git: 2fecdda
# Location: ~/how-git-works-lab
$ tree .git
.git/
├── HEAD
├── config
├── description
├── hooks
│ ├── applypatch-msg.sample
│ ├── commit-msg.sample
│ ├── fsmonitor-watchman.sample
│ ├── post-update.sample
│ ├── pre-applypatch.sample
│ ├── pre-commit.sample
│ ├── pre-push.sample
│ ├── pre-rebase.sample
│ ├── pre-receive.sample
│ ├── prepare-commit-msg.sample
│ └── update.sample
├── info/
│ └── exclude
├── objects/
│ ├── info/
│ └── pack/
└── refs/
├── heads/
└── tags/
這時候我有一個好奇,乍看之下 .git
目錄下也是有不少檔案和子目錄,那這些都是必要的嗎?有什麼是作為一個 Git 倉庫必備的存在呢?所以做了些實驗。
透過下面範例,我們暸解到並不是專案根目錄下面有一個 .git
目錄,Git 就會照單全收、認為這是一個 Git 倉庫。
# Location: ~
$ mkdir fake-git-repository
$ cd fake-git-repository
# Location: ~/fake-git-repository
$ mkdir .git
$ git status
fatal: not a git repository (or any of the parent directories): .git
接下來我又嘗試一個個把 .git
裡面原本存在的檔案和子目錄刪除,並在刪除某個檔案或目錄時,在專案根目錄下執行 git status
確認這個專案是否是一個 Git 倉庫。
最後得到以下目錄結構:
# [Repo] 61d0acc @ dot-git
# Location: ~/how-git-works-lab
$ tree .git
.git/
├── HEAD
├── objects/
└── refs/
objects
和 refs
是空目錄,而 HEAD
是一個文字檔,內容如下:
ref: refs/heads/master
所以只要符合上面目錄結構,且 HEAD
有這樣的文字目錄,就會被認可是一個 Git 倉庫。或許接下來我們就可以先專注在這些目錄與檔案,來暸解 Git 的操作到底是如何透過對 .git
目錄的修改,讓其變成一個版控資料庫的。
git init
的詳細介紹