生活中常常有這樣的場景,你寫一個文檔屹堰,想退回以前的某個狀態(tài),但發(fā)現(xiàn)沒有以前的存檔街氢〕都或者很多人協(xié)作做一個東西(比如和你的對象一起寫小說),但發(fā)現(xiàn)大家各自做的東西總是有沖突珊肃。遇到這樣的情況怎么辦呢(恐慌臉)荣刑,別怕,今天我給大家深入淺出的介紹一下git的基本的使用技巧伦乔。
首先厉亏,git是一個分布式版本控制系統(tǒng)。分布式版本控制烈和,意味著版本庫分布在每一個人的電腦上爱只,這樣你修改完后能直接提交到本地版本庫,如果別人要得到你的修改從你那復(fù)制一份就好了招刹。當(dāng)然恬试,一般我們會拿一臺中央服務(wù)器用來交換大家的修改沥匈。
給大家介紹一下安裝git的方法,這里是安裝git的方法
好的忘渔,我沒有偷懶高帖。
大家現(xiàn)在在命令行里輸入git,按回車畦粮,先看一下它的輸出散址,上面包括的最基本的用法簡介。
初次使用git宣赔,需要設(shè)置你的郵箱和名字预麸,比如:
$ git config --global user.name "Tian Flower Flower"
$ git config --global user.email flower@example.com
接著給大家介紹一下怎么使用這項強大的工具和你的小伙伴一起敲代碼。
首先建立一個空文件夾儒将,打開終端(windows用戶搜索cmd)吏祸,進(jìn)入那個文件夾下,然后輸入git init钩蚊,這時候那個文件夾就被git初始化了贡翘。還有一種初始化的方式,假如對方已經(jīng)寫了一部分代碼砰逻,你可以直接git clone 下來他的倉庫地址鸣驱。被git初始化后,文件夾就會出現(xiàn)一個新的隱藏文件夾.git蝠咆,于一個 Git 倉庫來說踊东,其 .git 目錄保存了整個 Git 項目的所有數(shù)據(jù)與資源。
現(xiàn)在你的目錄下有三個文件(它們已經(jīng)在本地倉庫里了),sing.py,dance.py,read.py刚操,然后你對它們每個文件都加了一行代碼闸翅。那么問題來了,你想提交到本地倉庫的時候附加上提交的備注菊霜,"修改了音樂的部分"和"修改了閱讀的部分"坚冀,你需要先提交sing.py、dance.py占卧,再提交read.py遗菠。同時為了便于管理這些文件联喘,git還會對這些文件建立狀態(tài)文件(你輸入git status就能看到狀態(tài)华蜒,輸入git status --help可以查看具體的參數(shù),其它的命令也是后面加個--help)豁遭。因為git一般是在命令行里使用的叭喜,所以為了便于添加文件,記錄文件狀態(tài)蓖谢,git有了暫存區(qū)的概念捂蕴,你可以通過git add sing.py dance.py將文件添加到暫存區(qū)譬涡,這個時候輸入git status,會發(fā)現(xiàn):
~/gitPresentation master ? ? ?
? git status
On branch master
No commits yet
Changes to be committed:
(use "git rm --cached <file>..." to unstage)
new file: dance.py
new file: sing.py
Untracked files:
(use "git add <file>..." to include in what will be committed)
read.py
由上面的信息可以看到dance.py和sing.py已經(jīng)被加入到了暫存區(qū)啥辨,changes to be commited就是告訴你這些變化待提交涡匀,(use "git rm --cached <file>..." to unstage)是告訴你可以用那個命令把文件從暫存區(qū)里弄出去。下半部分就是沒有在暫存區(qū)的溉知。
然后git commit -m "your message"就可以提交到本地倉庫了陨瘩。read.py的操作也是git add 然后 git commit。
這個時候我們查看一下.git/objects
~/gitPresentation master ? 0m
? find .git/objects -type f
.git/objects/fe/80e07a67b964e66cf2ac5abb611c3e4b351b33
.git/objects/d3/c9a190f400e0f4e5837c25be288540945e1492
.git/objects/b4/43902473907ac4832f821db909f98964ee9f3e
.git/objects/9d/9991b2ac7598604dad272072a4979fb48abddc
.git/objects/f0/2275089261d075a1b33ddb281c310d2365cb04
.git/objects/60/59d3d2e913d238833e9cf2707b5379794fafb3
.git/objects/7d/a981ddf41583e61b41385ca86c7ba5953bc545
可以看到這里有了很多對象级乍,那這個時候我們給read.py增加一個空行舌劳,提交后再輸入一下這個命令:
~/gitPresentation master ? 0m
? find .git/objects -type f
.git/objects/fe/80e07a67b964e66cf2ac5abb611c3e4b351b33
.git/objects/36/f4d833fae786bf32082e289808bc8988c039d2
.git/objects/d3/c9a190f400e0f4e5837c25be288540945e1492
.git/objects/6d/fbda7939f771046777e8858bc4d742b4be5e2c
.git/objects/b4/43902473907ac4832f821db909f98964ee9f3e
.git/objects/9d/9991b2ac7598604dad272072a4979fb48abddc
.git/objects/f0/2275089261d075a1b33ddb281c310d2365cb04
.git/objects/60/59d3d2e913d238833e9cf2707b5379794fafb3
.git/objects/7d/a981ddf41583e61b41385ca86c7ba5953bc545
.git/objects/7d/9a8143b3d66a8cb5178f7b780015bcfdaa46ea
可以發(fā)現(xiàn)對象變多了。
你每次修改文件提交后git都會把修改后的文件完整的存儲起來玫荣。你可能想git為什么不每次記錄修改的地方甚淡,按前面那種方法太浪費空間了。其實是可以的捅厂,git默認(rèn)使用松散對象來存儲文件贯卦,當(dāng)太多空間被浪費,或者推送到遠(yuǎn)程服務(wù)器的時候焙贷,git會調(diào)用git gc脸侥,來將松散對象打包好,來節(jié)省空間盈厘,在打包好的packfile中睁枕,git只存儲變化的部分,然后用一個指針指向之前的文件沸手。
我們可以手動調(diào)用git gc來試一下:
~/gitPresentation master ? 16m
? git count-objects -v
count: 10
size: 40
in-pack: 0
packs: 0
size-pack: 0
prune-packable: 0
garbage: 0
size-garbage: 0
~/gitPresentation master ? 16m
? git gc
Counting objects: 10, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (10/10), done.
Writing objects: 100% (10/10), done.
Total 10 (delta 0), reused 0 (delta 0)
~/gitPresentation master ? 16m
? git count-objects -v
count: 0
size: 0
in-pack: 10
packs: 1
size-pack: 2
prune-packable: 0
garbage: 0
size-garbage: 0
~/gitPresentation master ? 16m
? find .git/objects -type f
.git/objects/pack/pack-2c2c342dc3d81f01aa69d2bd2eedf5d4429264d9.pack
.git/objects/pack/pack-2c2c342dc3d81f01aa69d2bd2eedf5d4429264d9.idx
.git/objects/info/packs
~/gitPresentation master ? 16m
? ls
dance.py read.py sing.py
可以看到之前那十個松散對象都被打包好了外遇。
現(xiàn)在你想寫有關(guān)巴赫的代碼,你的朋友想寫有關(guān)莫扎特的代碼契吉,于是為了避免沖突跳仿,你創(chuàng)建了一個叫巴赫的分支,你的朋友創(chuàng)建了一個叫莫扎特的分支捐晶。(這里提醒一下菲语,git pull默認(rèn)只獲取遠(yuǎn)程的master分支,如果要checkout到遠(yuǎn)程其它的分支惑灵,首先要git branch -r山上,然后checkout到對應(yīng)的分支。)
現(xiàn)在你先checkout到Bach分支英支,進(jìn)行魔改操作佩憾,然后提交:
~/gitPresentation master ? 22m
? git checkout Bach
Switched to branch 'Bach'
~/gitPresentation Bach ? 29m
? ls
dance.py read.py sing.py
~/gitPresentation Bach ? 29m
? vim note.py
~/gitPresentation Bach ? 31m ?
? git add note.py
~/gitPresentation Bach ? 31m ?
? git commit -m "note"
[Bach 4f38850] note
1 file changed, 5 insertions(+)
create mode 100644 note.py
~/gitPresentation Bach ? 0m
? git log --oneline
4f38850 (HEAD -> Bach) note
36f4d83 (master, Mozart) add a empty line
b443902 read.py
7da981d music
你先把Bach分支合并到master分支:
~/gitPresentation master ? 37m
? git merge Bach
Updating 36f4d83..4f38850
Fast-forward
note.py | 5 +++++
1 file changed, 5 insertions(+)
create mode 100644 note.py
~/gitPresentation master ? 9m
? git log --oneline
4f38850 (HEAD -> master, Bach) note
36f4d83 add a empty line
b443902 read.py
7da981d music
你的朋友在Mozart分支下也創(chuàng)建了一個note.py。然后你想把Mozart分支也合并到master分支,那么問題來了妄帘,Mozart分支下也有note.py楞黄,內(nèi)容差不多,和master分支下的note.py沖突了抡驼,我們可以git diff一下:
~/gitPresentation master ? 11m
? git diff master Mozart
diff --git a/note.py b/note.py
index ce070d4..0c85471 100644
--- a/note.py
+++ b/note.py
@@ -1,5 +1,5 @@
def note():
- print('note')
+ print('Mozart')
if __name__ == '__main__':
note()
可以看出來有不同的地方鬼廓,我們需要手動處理沖突。
這里講一下git merge是如何判斷沖突的致盟,貼一段官方文檔里的話:
For conflicting paths, the index file records up to three versions: stage 1 stores the version from the common ancestor, stage 2 from HEAD, and stage 3 from MERGE_HEAD (you can inspect the stages with git ls-files -u). The working tree files contain the result of the "merge" program; i.e. 3-way merge results with familiar conflict markers <<< === >>>.
就是說兩個分支合并桑阶,先和公共的基點做對比,不然勾邦,要是一個分支比另一個分支多一個文件蚣录,你怎么知道是a分支增加了一個文件,還是b分支刪除了一個文件眷篇。
手動處理沖突后萎河,我們進(jìn)行合并,然后查看提交歷史:
~/gitPresentation master ? 25m
? git merge Mozart
Merge made by the 'recursive' strategy.
~/gitPresentation master ? 0m
? git log --graph --oneline
* 0cfd35e (HEAD -> master) Merge branch 'Mozart'
|\
| * cf331f2 (Mozart) solve
| * 756753d Mozart not
* | 4f38850 (Bach) note
|/
* 36f4d83 add a empty line
* b443902 read.py
* 7da981d music
可以看到現(xiàn)在Bach分支和Mozart分支都已經(jīng)合并到了master分支蕉饼,此時要記住最好刪除Bach分支和Mozart分支虐杯,避免歷史混亂。
git還有一種合并方法叫rebase昧港,它的原理是將另一條分支上面提交的commit在master上重演一遍擎椰,但是因為rebase會改寫歷史記錄,所以不要在公共分支上用rebase创肥,不然可能一不小心达舒,你的朋友們都會仇恨你。不過這里提一個有用的rebase命令叹侄,如果你想修改上一個commit信息巩搏,自然是用git commit --amend,但是修改很久之前的呢趾代,可以用git rebase -i(查看git rebase --help的INTERACTIVE MODE)贯底。
好,git今天就簡單的講到這了撒强,謝謝大家禽捆。