初窺Git

張嘉軒
張嘉軒
Feb 25, 2017 · 12 min read

One of your tabs

寫這篇文章,主要是想給我的同學們。最近有一堂課需要用到Git來交作業、考試等等,所以助教上了一堂課,講解了Git是什麼、怎麼使用,但有「一部份」的人好像完全不懂,這到底是什麼、我為什麼要用它,為什麼我照著助教說的做卻有問題。

嗯…,我想想我一開始學習Git的時候的情景…

我學新東西的習慣是:

  1. google 關鍵字
  2. 開一堆分頁
  3. 篩選掉看不習慣的
  4. 再慢慢對照著讀,配合一些練習

那我給我這篇文章的定位是,能夠在我自己的篩選下存活下來的。我並沒有想寫一篇,「你看這個就好」的文章。你還是需要看「很多」文章,但我希望這會是其中一篇,而且會是你會推薦給其他新手的。

推薦一起閱讀

很棒的 slides,豐富的圖解,把很多觀念都解釋的很清楚。

但講得有點深,有些細節沒有講得很清楚,適合總綱性的閱讀。

不錯的教學文,還不錯,可以看看~(不過它有關安裝的連結好像過時了 0.0)

大量的圖解,這一整個 tutorial練習過一遍,基本使用就沒問題了。

非常仔細的文字解說(一樣有圖解 XD)。有時候看圖很容易懂,但會忽略掉一些細節,這時候可以對照著看。

前置作業一:安裝 Git

前置作業二:Open your Terminal

  • windows: Git Bash

在資料夾中,右鍵點 「Git Bash Here」,就可以打開了。

  • Mac, Linux: Terminal

先稍微講解一下 Terminal 是什麼:

Terminal 是一個介面;而 Git 是一個指令,所以你需要透過 Terminal 這個介面去跟 Git 這個指令做互動。

底下是 Git Bash 的初始畫面:

Git Bash

稍稍解釋一下:

  • USER是我的 username。
  • Lenovo-PC 是我的 hostname。
  • MINGW64 (略…)
  • ~/Desktop:當前路徑,代表你現在所在的位置,是在哪個資料夾中。像我現在就是在桌面。

Mac 或其他環境,看到的可能不太一樣。基本上只要注意路徑這個欄位就好了。

但裡面還是有很多奇怪的符號欸?

符號常常被用來表示一些抽象的概念,譬如:從 A點到 B點,我們會點兩個點,再用一個箭頭將他們連起來。

  • @ :這應該算一種習慣,預設的 prompt 經常以 (USERNAME)@(HOSTNAME) 做為prompt(這又是啥?!別急,後面會解釋)。
  • ~ :代表家目錄(home directory),因為很常用,所以用個符號代表。(想看自己的家目錄在哪,可以打 echo $HOME )
  • / :這個我就不講太細了。代表目錄之間的關係,例如: ~/Desktop 就是家目錄下的 Desktop 這個資料夾。

Windows 環境下,平常看到的可能是另一個符號: \ (反鈄線 backslash)。

原本的是 / (鈄線 slash),表達路徑主要都會用這個符號,只要知道 Windows 跟人家不太一樣就好。

  • $ :這個符號加上前面所有的東西,就是 prompt (簡單講,就是圖片上那兩行)。後面就可以打上 command,來與 shell 作互動。

可能還是會看到一些不熟悉的名詞,譬如 shell 又是什麼?之類的。但沒關係,這些都只是名詞,以後有機會可以再獨立出來談。

做個簡單的比喻,shell 是法官,你是被告,那 prompt 就是法官問:「被告,你有什麼要辯解的?」,然後你就可以開始回答了。

所以他沒問,你就不能答,你答了,他也不會理你。

所以看到 prompt 再打 command!

下面再講解 command 的時候,整個 prompt 會用一個 $ 代替:

# (井字號後的字,代表註解)
$ command

Some shell commands

雖然這篇不是在講 shell ,但我們還是需要熟悉一些基本的操作,才有辦法配合 Git 作使用。

  • ls :list。列出當前資料夾下,有哪些檔案、資料夾。
# 當前目錄下有哪些檔案
$ ls
# some-dir 裡有哪些檔案
$ ls some-dir
# 列出隱藏的檔案(檔名以一個.開頭的檔案)
$ ls -a
  • cd :change directory 的縮寫,如字面上的意思,被用來改變你的位置(在哪個資料夾中)。你在檔案總管裡,進入一個資料夾,就是 cd 的意思。
# 進入 some-dir 資料夾中
$ cd some-dir
# 回到上一層的目錄,".."(兩個點) 代表上一層的目錄
$ cd ..
# 只打cd會回到家目錄
$ cd
# 跟上一個指令同樣效果,不過使用了家目錄的代稱"~"。
$ cd ~

Tip. <Tab> 有自動補全(auto complete)的功能,可以嘗試看看。

  • touch :常被用來創造新的檔案。(類似新增一個空的文字文件的效果)
$ touch filename
  • mkdir :可以創檔案,當然也可以創資料夾囉~
$ mkdir some-dir

好我現在總共教了四個command,回想一下有哪些?分別有什麼功用?

補充.

有沒有覺得我是不是漏講了什麼?對,編輯!

創了檔案,卻沒教怎麼修改?!

編輯器的選擇有很多,每個人習慣不同,可以自行 google 自己慣用的編輯器在 Terminal 中對應的 command 是什麼。

我選擇教一個折衷的方式:

如何在當前路徑開啟檔案管理器。

再用任何你以前習慣的方式去編輯檔案。

當你在 Terminal,用 ls 看到想要編輯的檔案的時候,打 start . (In Windows),會在當前路徑開啟檔案總管;如果是 Mac 的話,則是打 open . 一樣會開啟 Finder。

沒提 Linux,是因為在不同的環境下,可能用著不同的檔案管理器,命令也不太一樣,不太好統整出一個比較統一的說法。可以試著用這樣的關鍵字 google 看看:

“ubuntu open file manager current directory terminal” (自行把 ubuntu 換成自己的 distribution)

切入正題,Git

相信會來看這篇文章的,在座的各位都知道什麼是Git了。你們可能已經照著某種教學,用git做了某些練習,但你可能不是很暸解發生了什麼,或甚至你連照著做都遇到了某些問題。

git,是不能直接使用的,它必須在所謂的git repository中才能發揮作用。

git repository:也是一個資料夾,但又不只是資料夾。

有兩種方式來創造一個repository:

git init

(記得跟上面 shell command 的部份對照著看)

  • 在家目錄(~)中創造了一個資料夾(命名為”git-by-init”)
  • cd 進去
  • git init 初始化

magic 在此發生:這個命令把一個普通的資料夾變成 git repository

Tips. 用 ls -a 觀察看看 git init 前後發生了什麼事~

  • git status :這是 git 一個非常基本、重要的命令。用來察看現在 git repository 中發生了什麼事,再作對應的操作。
  • cd .. :這邊回到上層目錄,是為了比較 普通的資料夾git repository 的差別。

git clone

相對於 git init 是創一個空的資料夾,從零開始; git clone 則是在網路上,例如:GitHub 或 GitLab 上,已經存在一個 project ,你想要下載下來,就可以用這個 command。

$ git clone <url>

url的部份,根據要下載的repository是放在哪個網站,複製網址的地方不太一樣。(看圖應該很好懂,這邊提供 GitHub, GitLab 的載圖)

點右邊的「 Clone or download」,再點「 Copy to clipboard」

中間就是 url,記得左邊要選成 「 HTTPS」。

clone 下來之後,會自動以 Project 的名稱,作為 repository 的名稱。

整體看起來還比用 git init 簡單一些,畢竟是 clone 現成的 repository!

Review.

所以現在學到要創造一個 git repository,有兩種方式:

  1. git init :從無到有,先創造一個空資料夾,再用 git init 將它轉換成 git repository。
  2. git clone :網路上已經有現成的 repository,找到它的url,就可以clone下來了。

Configuration

在使用之前,我們需要先設定一下,讓 Git 知道你的基本資料,因為 Git 在記錄改變的同時,也會記錄下是誰進行操作的。

# username
$ git config --global user.name "your name"
# email
$ git config --global user.email "foo@example.com

設定完,可以用 git config --list 去看現在有哪些 configuration。

或者,用編輯器開啟 ~/.gitconfig 來察看。


接下來終於可以正式使用了,主要使用的command是

  • git status (前面提到過):觀察現在git repository中有什麼變化。
  • git add:將「改變」新增到 staging area。
  • git commit -m "msg" :將之前用 git add 所加入的所有改變,配合一段描述訊息(msg),記錄成一個commit。
  • git log --oneline :列出 commit log。(可以試試看不加 --oneline會發生什麼事)。

下面配合載圖說明:

先確定自己處在 git repository 之中( git status )

創造一個 new-file 之後

可以看到 git status 回報有一個 Untracked files

(標示為色)

照著git的指示,使用 git add

將 new-file 加入 staging area

一樣用 git status 去察看狀態

可以看到 new-file 的狀態變成是Changes to be committed

(標示為色)

也就是我所說的staging area

add 之後,就可以commit了

訊息的內容,說明了我這次的commit 主要改變是:新增了一個檔案。

可以用 git log --oneline 去看之前的 commit log

這樣就是最基本的git操作流程了:

  1. 在 git repository 中,對檔案進要一些操作,包含:新增、編輯、重新命名、移動位置、刪除等等。
  2. 再用 git add新增」這些「改變」。

(1、2步可以重覆多次,再進行 commit)

3. 配合一段具描述性的訊息,將前面所 add 的改變,記錄成一個commit。

git 其實在過程中都會提示現在應該打哪些指令,注意看那些提示可以幫助你很多!

git add 是在add什麼?

git add 可能會混淆某些人,以為add是創造檔案之類的。實際上,比較像是把「改變」新增到 staging area 中。

我一直強調「改變」這件事,因為 git 的功能不像是在管理「檔案」,而是管理這些 「改變」。

想像一下,如果這些「改變」是一個東西,那 git add 就是把東西放進一個箱子裡,而 git commit 就是把箱子封起來,上面再寫上一段話,標示裡面放了什麼。

commit 的時機

Git 教學(1) : Git 的基本使用:裡面也有討論這個問題,可以對照著看!

前面提到可以一次 add 很多改變再一起 commit,那到底什麼時候才是那個時機呢?

拿寫文章作比喻,你可以寫一個逗號就 commit 一次,也可以一個句號 commit 一次,同樣也可以一整段才 commit 一次。

我的建議是:

不要寫一個逗號就 commit 一次,commit log 會變得冗長、沒有重點。

最多寫一段就應該要 commit 了,並以一個合適的 subtitle 作為 commit message。

File Status Lifecycle

File Lifecycle 是一個很重要的觀念,關係到 git 是用什麼樣的方式,去看待檔案。

看圖應該可以有一個概略的理解,真正的細節推薦細讀下面這個連結:

Pro Git — 2nd edition — 2.2 Git 基礎 — 紀錄變更到版本庫中

Figure 8. The lifecycle of the status of your files.

( 寫給大家的 Git 教學 的第 19頁)

下面是我以自己對 life cycle 的理解畫的一個圖

問題

  1. 使用 git init 和 git clone 有什麼差別?如何用 git init 搭配其他指令做到 git clone 的效果?
  2. 在一個 Git Repository 中,建立一個新的資料夾和一個新的檔案,對 Git 來說有什麼差別?為什麼?

共勉之.

https://xkcd.com/1597/

張嘉軒

Written by

張嘉軒

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade