注:本文是通過廖雪峰官網的git學習教程整理出來的個人筆記
git的使用
git的安裝
sudo apt-get install git
- 安裝homebrew,然后通過homebrew安裝Git
- 直接從AppStore安裝Xcode,Xcode集成了Git,不過默認沒有安裝,需要運行Xcode,選擇菜單“Xcode”->“Preferences”,在彈出窗口中找到“Downloads”,選擇“Command Line Tools”,點“Install”就可以完成安裝了。
- window上安裝
- 安裝msysgit
- 安裝完成后,在開始菜單里找到“Git”->“Git Bash”,蹦出一個類似命令行窗口的東西,就說明Git安裝成功
初始化
- 因為Git是分布式版本控制系統,所以,每個機器都必須自報家門:你的名字和Email地址
$ git config --global user.name "Your Name"
$ git config --global user.email "email@example.com"
git初始化
$ mkdir gitDir
$ cd gitDir
$ pwd
/Users/michael/gitDir
$ git init
Initialized empty Git repository in /Users/michael/gitDir/.git/
- 所有的版本控制系統,其實只能跟蹤純文本文件的改動,比如TXT文件,網頁,所有的程序代碼等等,Git也不例外。
- 版本控制系統可以告訴你每次的改動,比如在第5行加了一個單詞“Linux”,在第8行刪了一個單詞“Windows”。
- 而圖片、視頻這些二進制文件,雖然也能由版本控制系統管理,但沒法跟蹤文件的變化,只能把二進制文件每次改動串起來,也就是只知道圖片從100KB改成了120KB,但到底改了啥,版本控制系統不知道,也沒法知道。
- word不是純文本文件,不能跟蹤具體修改了什么內容,只能跟蹤修改的大小和時間
使用Windows要特別注意:
- 千萬不要使用Windows自帶的記事本編輯任何文本文件。
- 原因是Microsoft開發記事本的團隊使用了一個非常弱智的行為來保存UTF-8編碼的文件,他們自作聰明地在每個文件開頭添加了0xefbbbf(十六進制)的字符,你會遇到很多不可思議的問題
- 比如,網頁第一行可能會顯示一個“?”,明明正確的程序一編譯就報語法錯誤,等等
- 建議你下載Notepad++代替記事本,不但功能強大,而且免費!記得把Notepad++的默認編碼設置為UTF-8 without BOM即可
添加版本控制
$ git add readme.txt
$ git commit -m "wrote a readme file"
[master (root-commit) cb926e7] wrote a readme file
1 file changed, 2 insertions(+)
create mode 100644 readme.txt
# -m 后面輸入的是本次提交的說明
$ git add file1.txt
$ git add file2.txt file3.txt
$ git commit -m "add 3 files."
$ git status
# On branch master
# Changes not staged for commit:
# (use "git add <file>..." to update what will be committed)
# (use "git checkout -- <file>..." to discard changes in working directory)
#
# modified: readme.txt
#
no changes added to commit (use "git add" and/or "git commit -a")
$ git diff readme.txt
diff --git a/readme.txt b/readme.txt
index 46d49bf..9247db6 100644
--- a/readme.txt
+++ b/readme.txt
@@ -1,2 +1,2 @@
- Git is a version control system.
+ Git is a distributed version control system.
Git is free software.
$ git add readme.txt
$ git status
# On branch master
# Changes to be committed:
# (use "git reset HEAD <file>..." to unstage)
#
# modified: readme.txt
#
git commit -m "add distributed"
[master ea34578] add distributed
1 file changed, 1 insertion(+), 1 deletion(-)
- 查看歷史記錄
- --pretty=oneline加上這個選項可以美化輸出效果
$ git log
commit 3628164fb26d48395383f8f31179f24e0882e1e0
Author: Michael Liao <askxuefeng@gmail.com>
Date: Tue Aug 20 15:11:49 2013 +0800
append GPL
commit ea34578d5496d7dd233c827ed32a8cd576c5ee85
Author: Michael Liao <askxuefeng@gmail.com>
Date: Tue Aug 20 14:53:12 2013 +0800
add distributed
commit cb926e7ea50ad11b8f9e909c05226233bf755030
Author: Michael Liao <askxuefeng@gmail.com>
Date: Mon Aug 19 17:51:55 2013 +0800
wrote a readme file
$ git log --pretty=oneline
3628164fb26d48395383f8f31179f24e0882e1e0 append GPL
ea34578d5496d7dd233c827ed32a8cd576c5ee85 add distributed
cb926e7ea50ad11b8f9e909c05226233bf755030 wrote a readme file
版本回退
- 首先,Git必須知道當前版本是哪個版本,在Git中,用HEAD表示當前版本,也就是最新的提交3628164...882e1e0(注意我的提交ID和你的肯定不一樣),上一個版本就是HEAD,上上一個版本就是HEAD,當然往上100個版本寫100個比較容易數不過來,所以寫成HEAD~100。
$ git reset --hard HEAD^
HEAD is now at ea34578 add distributed
- 如果后悔了,想回到最新的版本
- 只要上面的命令行窗口還沒有被關掉,你就可以順著往上找之前打印的log記錄,找到那個append GPL的commit id是3628164...,于是就可以指定回到未來的某個版本:
- 版本號沒必要寫全,前幾位就可以了,Git會自動去找。當然也不能只寫前一兩位,因為Git可能會找到多個版本號,就無法確定是哪一個了。
$ git reset --hard 3628164
HEAD is now at 3628164 append GPL
- 如果我想回退到最新版本,又重啟了電腦
- 在Git中,總是有后悔藥可以吃的。當你用$ git reset --hard HEAD^回退到add distributed版本時,再想恢復到append GPL,就必須找到append GPL的commit id。Git提供了一個命令git reflog用來記錄你的每一次命令:
- 終于舒了口氣,第二行顯示append GPL的commit id是3628164,現在,你又可以乘坐時光機回到未來了。
$ git reflog
ea34578 HEAD@{0}: reset: moving to HEAD^
3628164 HEAD@{1}: commit: append GPL
ea34578 HEAD@{2}: commit: add distributed
cb926e7 HEAD@{3}: commit (initial): wrote a readme file
- ++HEAD指向的版本就是當前版本因此,Git允許我們在版本的歷史之間穿梭,使用命令git reset --hard commit_id。++
- ++穿梭前,用git log可以查看提交歷史,以便確定要回退到哪個版本。++
- ++要重返未來,用git reflog查看命令歷史,以便確定要回到未來的哪個版本。++
工作區和暫存區
- 工作區有一個隱藏目錄.git,這個不算工作區,而是Git的版本庫
- Git的版本庫里存了很多東西,其中最重要的就是稱為stage(或者叫index)的暫存區,還有Git為我們自動創建的第一個分支master,以及指向master的一個指針叫HEAD
- 前面講了我們把文件往Git版本庫里添加的時候,是分兩步執行的:
- 第一步是用git add把文件添加進去,實際上就是把文件修改添加到暫存區;
- 第二步是用git commit提交更改,實際上就是把暫存區的所有內容提交到當前分支。
- 因為我們創建Git版本庫時,Git自動為我們創建了唯一一個master分支,所以,現在,git commit就是往master分支上提交更改。
- 你可以簡單理解為,需要提交的文件修改通通放到暫存區,然后,一次性提交暫存區的所有修改。
管理修改
- Git比其他版本控制系統設計得優秀,是因為Git跟蹤并管理的是修改,而非文件。
- 第一次修改 -> git add -> 第二次修改 -> git commit
- Git管理的是修改,當你用git add命令后,在工作區的第一次修改被放入暫存區
- 準備提交,但是,在工作區的第二次修改并沒有放入暫存區
- 所以,git commit只負責把暫存區的修改提交了,也就是第一次的修改被提交了,第二次的修改不會被提交。
撤銷修改
$ git status
# On branch master
# Changes not staged for commit:
# (use "git add <file>..." to update what will be committed)
# (use "git checkout -- <file>..." to discard changes in working directory)
#
# modified: readme.txt
#
no changes added to commit (use "git add" and/or "git commit -a")
- git checkout -- file可以丟棄工作區的修改
$ git checkout -- readme.txt
- 命令git checkout --readme.txt意思就是,把readme.txt文件在工作區的修改全部撤銷
- 這里有兩種情況:
- 一種是readme.txt自修改后還沒有被放到暫存區,現在,撤銷修改就回到和版本庫一模一樣的狀態;
- 一種是readme.txt已經添加到暫存區后,又作了修改,現在,撤銷修改就回到添加到暫存區后的狀態。
- 總之,就是讓這個文件回到最近一次git commit或git add時的狀態。
- git checkout -- file命令中的--很重要,沒有--,就變成了“切換到另一個分支”的命令,我們在后面的分支管理中會再次遇到git checkout命令。
$ cat readme.txt
Git is a distributed version control system.
Git is free software distributed under the GPL.
Git has a mutable index called stage.
Git tracks changes of files.
My stupid boss still prefers SVN.
$ git add readme.txt
- commit之前,你發現了這個問題。用git status查看一下,修改只是添加到了暫存區,還沒有提交:
$ git status
# On branch master
# Changes to be committed:
# (use "git reset HEAD <file>..." to unstage)
#
# modified: readme.txt
- Git同樣告訴我們,用命令git reset HEAD file可以把暫存區的修改撤銷掉(unstage),重新放回工作區:
$ git reset HEAD readme.txt
Unstaged changes after reset:
M readme.txt
- 場景1:當你改亂了工作區某個文件的內容,想直接丟棄工作區的修改時,用命令git checkout -- file。
- 場景2:當你不但改亂了工作區某個文件的內容,還添加到了暫存區時,想丟棄修改,分兩步,第一步用命令git reset HEAD file,就回到了場景1,第二步按場景1操作。
- 場景3:已經提交了不合適的修改到版本庫時,想要撤銷本次提交,參考版本回退一節,不過前提是沒有推送到遠程庫。
刪除文件
$ git add test.txt
$ git commit -m "add test.txt"
[master 94cdc44] add test.txt
1 file changed, 1 insertion(+)
create mode 100644 test.txt
$ rm test.txt
$ git status
# On branch master
# Changes not staged for commit:
# (use "git add/rm <file>..." to update what will be committed)
# (use "git checkout -- <file>..." to discard changes in working directory)
#
# deleted: test.txt
#
no changes added to commit (use "git add" and/or "git commit -a")
- 現在你有兩個選擇,一是確實要從版本庫中刪除該文件,那就用命令git rm刪掉,并且git commit:
$ git rm test.txt
rm 'test.txt'
$ git commit -m "remove test.txt"
[master d17efd8] remove test.txt
1 file changed, 1 deletion(-)
delete mode 100644 test.txt