基本用法(上)
一、實驗說明
本節實驗為 Git 入門第一個實驗,可以幫助大家熟悉如何創建和使用 git 倉庫。
二、git的初始化
在使用git進行代碼管理之前,我們首先要對git進行初始化。
1.Git 配置
使用Git的第一件事就是設置你的名字和email
,這些就是你在提交commit
時的簽名,每次提交記錄里都會包含這些信息。使用git config
命令進行配置:
$ git config --global user.name "Scott Chacon" $ git config --global user.email "schacon@gmail.com"
執行了上面的命令后,會在家目錄(/home/shiyanlou
)下建立一個叫.gitconfig
的文件(該文件為隱藏文件,需要使用ls -al
查看到). 內容一般像下面這樣,可以使用vim或cat查看文件內容:
$ cat ~/.gitconfig
[user]
email = schacon@gmail.com
name = Scott Chacon
上面的配置文件就是Git全局配置的文件,一般配置方法是git config --global <配置名稱> <配置的值>
。
如果你想使項目里的某個值與前面的全局設置有區別(例如把私人郵箱地址改為工作郵箱),你可以在項目中使用git config
命令不帶 --global
選項來設置. 這會在你當前的項目目錄下創建 .git/config
,從而使用針對當前項目的配置。
三、獲得一個Git倉庫
既然我們現在把一切都設置好了,那么我們需要一個Git倉庫。有兩種方法可以得到它:一種是從已有的Git倉庫中clone (克隆,復制);還有一種是新建一個倉庫,把未進行版本控制的文件進行版本控制。
1.Clone一個倉庫
為了得一個項目的拷貝(copy),我們需要知道這個項目倉庫的地址(Git URL). Git能在許多協議下使用,所以Git URL可能以ssh://, http(s)://, git://. 有些倉庫可以通過不只一種協議來訪問。
我們在git.shiyanlou.com
上提供了一個名字為gitproject
的供大家測試的公有倉庫,這個倉庫可以使用下面方式進行clone:
$ git clone http://git.shiyanlou.com/shiyanlou/gitproject
clone操作完成后,會發現當前目錄下多了一個gitproject
文件夾,這個文件夾里的內容就是我們剛剛clone下來的代碼。由於當前`gitproject僅是測試項目,里面僅有一個README.md文件。
$ cd gitproject/
(master)$ ls
README.md
細心的同學可以發現在命令提示符$
前面多了個(master)
。這是由於實驗樓的Linux使用的是zsh Shell,zsh會判斷當前的目錄是否有Git倉庫,如果是的話則自動把目前所在的git分支顯示在提示符中。Git 分支的概念我們會在稍后介紹。
2.初始化一個新的倉庫
可以對一個已存在的文件夾用下面的命令讓它置於Git的版本控制管理之下。
創建代碼目錄project
:
$ cd /home/shiyanlou/
$ mkdir project
進入到代碼目錄,創建並初始化Git倉庫:
$ cd project
$ git init
Git會輸出:
Initialized empty Git repository in /home/shiyanlou/project/.git/
通過ls -la
命令會發現project目錄下會有一個名叫.git
的目錄被創建,這意味着一個倉庫被初始化了。可以進入到.git
目錄查看下有哪些內容。
四、正常的工作流程
1. 正常的工作流程
git的基本流程如下:
- 創建或修改文件
- 使用
git add
命令添加新創建或修改的文件到本地的緩存區(Index) - 使用
git commit
命令提交到本地代碼庫 - (可選,有的時候並沒有可以同步的遠端代碼庫)使用
git push
命令將本地代碼庫同步到遠端代碼庫
進入我們剛才建立的project
目錄,分別創建文件file1
,file2
,file3
:
$ cd project
$ touch file1 file2 file3
修改文件,可以使用vim編輯內容,也可以直接echo添加測試內容。
$ echo "test" >> file1 $ echo "test" >> file2 $ echo "test" >> file3
此時可以使用git status
命令查看當前git倉庫的狀態:
$ git status
On branch master
Initial commit Untracked files: (use "git add <file>...") to include in what will be committed) file1 file2 file3 nothing added to commit but untracked files present (use "git add" to track)
可以發現,有三個文件處於untracked
狀態,下一步我們就需要用git add
命令將他們加入到緩存區(Index)。
使用git add
命令將新建的文件添加到:
$ git add file1 file2 file3
然后再次執行git status
就會發現新的變化:
$ git status
On branch master
Initial commit Changes to be committed: (use "git rm --cached <file>..." to unstage) new file: file1 new file: file2 new file: file3
你現在為commit
做好了准備,你可以使用 git diff
命令再加上 --cached
參數,看看緩存區中哪些文件被修改了。進入到git diff --cached
界面后需要輸入q
才可以退出:
$ git diff --cached
如果沒有--cached
參數,git diff
會顯示當前你所有已做的但沒有加入到索引里的修改。
如果你要做進一步的修改, 那就繼續做, 做完后就把新修改的文件加入到緩存區中。
當所有新建,修改的文件都被添加到了緩存區,我們就要使用git commit
提交到本地倉庫:
$ git commit -m "add 3 files"
需要使用-m
添加本次修改的注釋,完成后就會記錄一個新的項目版本。除了用git add
命令,我們還可以用下面的命令將所有沒有加到緩存區的修改也一起提交,但-a
命令不會添加新建的文件。
$ git commit -a -m "add 3 files"
再次輸入git status
查看狀態,會發現當前的代碼庫已經沒有待提交的文件了,緩存區已經被清空。
至此,我們完成了第一次代碼提交,這次提交的代碼中我們創建了三個新文件。需要注意的是如果是修改文件,也需要使用git add
命令添加到緩存區才可以提交。如果是刪除文件,則直接使用git rm
命令刪除后會自動將已刪除文件的信息添加到緩存區,git commit
提交后就會將本地倉庫中的對應文件刪除。
這個時候如果本地的倉庫連接到了遠程Git服務器,可以使用下面的命令將本地倉庫同步到遠端服務器:
$ git push origin master
這時候可能需要你輸入在Git服務器上的用戶名和密碼。可以參考實驗樓的代碼庫中的說明練習這個命令。
五、分支與合並
Git的分支可以讓你在主線(master分支)之外進行代碼提交,同時又不會影響代碼庫主線。分支的作用體現在多人協作開發中,比如一個團隊開發軟件,你負責獨立的一個功能需要一個月的時間來完成,你就可以創建一個分支,只把該功能的代碼提交到這個分支,而其他同事仍然可以繼續使用主線開發,你每天的提交不會對他們造成任何影響。當你完成功能后,測試通過再把你的功能分支合並到主線。
1.分支
一個Git倉庫可以維護很多開發分支。現在我們來創建一個新的叫 experimental的分支:
$ git branch experimental
運行git branch
命令可以查看當前的分支列表,已經目前的開發環境處在哪個分支上:
$ git branch
experimental
* master
experimental 分支是你剛才創建的,master分支是Git系統默認創建的主分支。星號標識了你當工作在哪個分支下,輸入git checkout 分支名
可以切換到其他分支:
$ git checkout experimental
Switched to branch 'experimental'
切換到experimental
分支,切換完成后,先編輯里面的一個文件,再提交(commit)改動,最后切換回 “master”分支:
# 修改文件file1 $ echo "update" >> file1 # 查看當前狀態 $ git status # 添加並提交file1的修改 $ git add file1 $ git commit -m "update file1" # 查看file1的內容 $ cat file1 test update # 切換到master分支 $ git checkout master
查看下file1
中的內容會發現剛才做的修改已經看不到了。因為剛才的修改時在experimental
分支下,現在切換回了master
分支,目錄下的文件都是master
分支上的文件了。
現在可以在master
分支下再作一些不同的修改:
# 修改文件file2 $ echo "update again" >> file2 # 查看當前狀態 $ git status # 添加並提交file2的修改 $ git add file2 $ git commit -m "update file2 on master" # 查看file2的內容 $ cat file2 test update again
這時,兩個分支就有了各自不同的修改,分支的內容都已經不同,如何將多個分支進行合並呢?
可以通過下面的git merge
命令來合並experimental
到主線分支master
:
# 切換到master分支 $ git checkout master # 將experimental分支合並到master $ git merge -m 'merge experimental branch' experimental
-m
參數仍然是需要填寫合並的注釋信息。
由於兩個branch修改了兩個不同的文件,所以合並時不會有沖突,執行上面的命令后合並就完成了。
如果有沖突,比如兩個分支都改了一個文件file3,則合並時會失敗。首先我們在master分支上修改file3文件並提交:
# 切換到master分支 $ git checkout master # 修改file3文件 $ echo "master: update file3" >> file3 # 提交到master分支 $ git commit -a -m 'update file3 on master'
然后切換到experimental,修改file3並提交:
# 切換到experimental分支 $ git checkout experimental # 修改file3文件 $ echo "experimental: update file3" >> file3 # 提交到master分支 $ git commit -a -m 'update file3 on experimental'
切換到master進行合並:
$ git checkout master
$ git merge experimental Auto-merging file3 CONFLICT (content): Merge conflict in file3 Automatic merge failed; fix conflicts and then commit the result.
合並失敗后先用git status
查看狀態,會發現file3顯示為both modified
,查看file3內容會發現:
$ cat file3
test
<<<<<<< HEAD
master: update file3 ======= experimental: update file3 >>>>>>> experimental
上面的內容也可以使用git diff
查看,先前已經提到git diff
不加參數可以顯示未提交到緩存區中的修改內容。
可以看到沖突的內容都被添加到了file3中,我們使用vim編輯這個文件,去掉git自動產生標志沖突的<<<<<<
等符號后,根據需要只保留我們需要的內容后保存,然后使用git add file3
和git commit
命令來提交合並后的file3內容,這個過程是手動解決沖突的流程。
# 編輯沖突文件 $ vim file3 # 提交修改后的文件 $ git add file3 $ git commit -m 'merge file3'
當我們完成合並后,不再需要experimental
時,可以使用下面的命令刪除:
$ git branch -d experimental
git branch -d
只能刪除那些已經被當前分支的合並的分支. 如果你要強制刪除某個分支的話就用git branch –D
2.撒銷一個合並
如果你覺得你合並后的狀態是一團亂麻,想把當前的修改都放棄,你可以用下面的命令回到合並之前的狀態:
$ git reset --hard HEAD^
# 查看file3的內容,已經恢復到合並前的master上的文件內容 $ cat file3
3.快速向前合並
還有一種需要特殊對待的情況,在前面沒有提到。通常,一個合並會產生一個合並提交(commit), 把兩個父分支里的每一行內容都合並進來。
但是,如果當前的分支和另一個分支沒有內容上的差異,就是說當前分支的每一個提交(commit)都已經存在另一個分支里了,git 就會執行一個“快速向前"(fast forward)操作;git 不創建任何新的提交(commit),只是將當前分支指向合並進來的分支。
六、Git日志
1.查看日志
git log命令可以顯示所有的提交(commit):
$ git log
如果提交的歷史紀錄很長,回車會逐步顯示,輸入q
可以退出。
git log
有很多選項,可以使用git help log
查看,例如下面的命令就是找出所有從"v2.5“開始在fs目錄下的所有Makefile的修改:
$ git log v2.5.. Makefile fs/
Git會根據git log命令的參數,按時間順序顯示相關的提交(commit)。
2.日志統計
如果用--stat選項使用'git log',它會顯示在每個提交(commit)中哪些文件被修改了, 這些文件分別添加或刪除了多少行內容,這個命令相當於打印詳細的提交記錄:
$ git log --stat
3.格式化日志
你可以按你的要求來格式化日志輸出。--pretty
參數可以使用若干表現格式,如oneline
:
$ git log --pretty=oneline
或者你也可以使用 short
格式:
$ git log --pretty=short
你也可用medium
,full
,fuller
,email
或raw
。 如果這些格式不完全符合你的相求, 你也可以用--pretty=format
參數定義格式。
--graph
選項可以可視化你的提交圖(commit graph),會用ASCII字符來畫出一個很漂亮的提交歷史(commit history)線:
$ git log --graph --pretty=oneline
4.日志排序
日志記錄可以按不同的順序來顯示。如果你要指定一個特定的順序,可以為git log
命令添加順序參數。
按默認情況,提交會按逆時間順序顯示,可以指定--topo-order
參數,讓提交按拓撲順序來顯示(就是子提交在它們的父提交前顯示):
$ git log --pretty=format:'%h : %s' --topo-order --graph
你也可以用 --reverse
參數來逆向顯示所有提交日志。
七、小結
本節講解了幾個基本命令:
- git config:配置相關信息
- git clone:復制倉庫
- git init:初始化倉庫
- git add:添加更新內容到索引中
- git diff:比較內容
- git status:獲取當前項目狀況
- git commit:提交
- git branch:分支相關
- git checkout:切換分支
- git merge:合並分支
- git reset:恢復版本
- git log:查看日志