簡介
Git 是一個免費的開源分布式版本控制系統(tǒng)撒璧,用于高效地處理從小型到大型的各種項目群扶。它由 Linus Torvalds 于 2005 年創(chuàng)建及刻,旨在管理 Linux 內(nèi)核開發(fā)。Git 以其速度竞阐、數(shù)據(jù)完整性和分布式工作流的靈活性而聞名缴饭,已成為軟件開發(fā)中最受歡迎的版本控制工具之一。
原理(https://git-scm.com/book/en/v2)
其本質(zhì)是一個基于 Key-Value 的內(nèi)容尋址文件系統(tǒng)骆莹,核心部分是一個簡單的鍵值對數(shù)據(jù)庫(key-value data store)
1 git文件系統(tǒng)的結(jié)構(gòu)如下
COMMIT_EDITMSG最后一次提交備注信息
FETCH_HEAD 保存了遠程倉庫中每個分支
ORIG_HEAD當(dāng)前分支最新的提交
config 文件包含項目特有的配置選項
description 文件僅供 GitWeb 程序使用
hooks 目錄包含客戶端或服務(wù)端的鉤子腳本(hook scripts)
info 目錄包含一個全局性排除(global exclude)文件
packed-refs 拉取遠端的所有分支颗搂,標(biāo)簽
refs 目錄存儲指向數(shù)據(jù)(分支、遠程倉庫和標(biāo)簽等)的提交對象的指針
logs引用日志數(shù)據(jù)
HEAD 文件指向目前被檢出的分支
objects 目錄存儲所有數(shù)據(jù)內(nèi)容
index 文件保存暫存區(qū)信息汪疮。
2 objects 存儲方式
在 Git 文件系統(tǒng)中峭火,使用Object 存儲所有類型的內(nèi)容,也稱為 Git 對象智嚷,不同類型的 Object 共同構(gòu)成了一整套對象模型卖丸。
3 Git 對象模型主要包括以下 4 種對象
● 二進制對象(Blob Object)存儲文件內(nèi)容。
● 樹對象(Tree Object)目錄類型文件
● 提交對象(Commit Object)
● 標(biāo)簽對象(Tag Object)
在 Git 文件系統(tǒng)中盏道,使用一個 40 位的 SHA-1 值 作為一個文件或目錄存儲內(nèi)容時所占用的,一個 Object 文件的唯一標(biāo)識符稍浆,在進行匹配查找時候,其中前 2 位 SHA-1 值作為存儲子目錄猜嘱,后 38 位 SHA-1 值作為文件名衅枫。
git所有對象均存儲在 .git/objects/ 目錄下,并采用相同格式進行表示: 類型 + 空格 + 存儲內(nèi)容
可以使用底層命令 git cat-file 來查看倉庫的一個 git Object 的存儲內(nèi)容
查看對象的類型 git cat-file -t SHA-1
查看對象的內(nèi)容長度 git cat-file -s SHA-1
查看對象的內(nèi)容 git cat-file -p SHA-1
下面分析下提交對象
下圖是一個提交對象(Commit Object)
tree aaaa5e107a54b94dc11d45420a31cbd6c77cb244: 表示提交文件所處的文件目錄
parent 7557a68d51cfa50194c8be76e4b59e787a2d26e9: 上一次提交所生成的哈希值
分析下樹對象(Tree Object)目錄類型文件
里面包含了下一級的樹對象(Tree Object)以及二進制對象(Blob Object)可以進一步通過git cat-file -p SHA-1命令查看內(nèi)容
如果直接查看二進制對象(Blob Object)可以直接看到文件的具體內(nèi)容
4 包文件
如果兩次提交同一個文件朗伶,Git 也會用一個全新的對象來存儲新的文件內(nèi)容弦撩,你的磁盤上現(xiàn)在有兩個幾乎完全相同的對象。
如果 Git 只完整保存其中一個论皆,再保存另一個對象與之前版本的差異內(nèi)容益楼,豈不更好猾漫?
事實上 Git 可以那樣做。 Git 最初向磁盤中存儲對象時所使用的格式被稱為“松散(loose)”對象格式感凤。 但是悯周,Git 會時不時地將多個這些對象打包成一個稱為“包文件(packfile)”的二進制文件,以節(jié)省空間和提高效率陪竿。 當(dāng)版本庫中有太多的松散對象禽翼,或者你手動執(zhí)行 git gc 命令,或者你向遠程服務(wù)器執(zhí)行推送時族跛,Git 都會這樣做闰挡。 要看到打包過程,你可以手動執(zhí)行 git gc 命令讓 Git 對對象進行打包庸蔼,這樣可以大大節(jié)約你的磁盤存儲
下面是手動進行g(shù)it gc 命令后的文件夾
打包后還保留著的幾個文件夾的對象是未被任何提交記錄引用的數(shù)據(jù)對象
剩下的文件會新創(chuàng)建的包文件和一個索引
Git 打包對象時解总,會查找命名及大小相近的文件,并只保存文件不同版本之間的差異內(nèi)容姐仅。
你可以查看包文件花枫,觀察它是如何節(jié)省空間的。 git verify-pack 這個底層命令可以讓你查看已打包的內(nèi)容:
git使用
Mac上安裝git方法:通過Xcode安裝 $ xcode-select --install
配置git用戶信息(git提交所帶的用戶信息):
git config user.name ; git config —global user.name
git config email ; git config —global user.email
注意事項:在同一臺電腦上更換gitlab的賬號時需要把電腦鑰匙串里面之前存儲的賬號密碼刪除掏膏。
1 Git本地操作
工作區(qū):我們平時編輯代碼的目錄文件夾
暫存區(qū):用于臨時存放你的改動(git add .)
提交修改到本地:只提交暫存區(qū)的修改: git commit git commit -m “提交信息”
把暫存區(qū)的修改回退到工作區(qū): git reset HEAD flie
丟棄工作區(qū)的修改: git checkout -- file
回退到上一次的提交: git reset -- hard HEAD^
回退到某一次提交:
● git log 獲取某一次的提交commitId
● git reset -- hard commitId
恢復(fù)回退的提交: git reflog獲得commitId
2分支管理
遠程庫克隆: git clone 遠程庫地址
查看遠程庫的信息: git remote
查看遠程庫詳細信息: git remote -v
創(chuàng)建分支同時切換分支: git checkout -b 分支名或者: git switch -c 分支名
創(chuàng)建分支: git branch 分支名
切換分支: git checkout 分支名或者: git switch 分支名
查看分支: git branch
推送分支: git push origin 分支名字
分支合并: git merge 要合并的分支名字 或者: git merge --no-ff -m “提交信息” 分支名
當(dāng)前分支變基到目標(biāo)分支(即 master)上:git rebase master
server分支變基到目標(biāo)分支(即 master)上:git rebase master server
選中在 client 分支里但不在 server 分支里的修改劳翰,將它們在 master 分支上重放作為 client 分支: git rebase --onto master server client
將某一個分支中的一段提交同時應(yīng)用到其master分支中: git rebase commit1 commit2 --onto master
刪除某一個分支的一系列提交: git rebase --onto 分支名~5 分支名~3 分支名(需要未push的提交,否則需要強制push)
交互式變基(交互式變基可以把多個提交合并成一個提交): git rebase -i master (操作未推到服務(wù)器的提交)
指定的提交(commit)應(yīng)用于其他分支: git cherry-pick commitID
指定的多個提交應(yīng)用于其他分支: git cherry-pick commitID1 commitID2
轉(zhuǎn)移一系列的連續(xù)提交: git cherry-pick commitID1..commitID2
刪除本地分支: git branch -d 分支名
強行刪除分支: git branch -D 分支名
刪除遠程分支: git push origin --delete 分支名
回滾遠程提交:
● 本地代碼回滾到某一次提交: git reset --hard commitID
● 加入-f參數(shù)馒疹,強制提交佳簸,遠程端將強制跟新到reset版本: git push -f origin 分支名
3 儲藏功能
儲藏功能 把當(dāng)前工作現(xiàn)場“儲藏”起來: git stash 或者: git stash save “信息”
恢復(fù)暫存恢復(fù)后,stash內(nèi)容并不刪除: git stash apply
恢復(fù)暫存恢復(fù)后颖变,stash內(nèi)容刪除: git stash pop
查看暫存列表: git stash list
恢復(fù)某一個暫存: git stash apply stash@{0}
4 標(biāo)簽管理
默認標(biāo)簽是打在當(dāng)前的內(nèi)置最新提交的commit上的.
查看所有標(biāo)簽: git tag
打新標(biāo)簽: git tag 標(biāo)簽名
打之前提交的標(biāo)簽:
● Git log找到歷史提commit id, 然后打上: git tag 標(biāo)簽名 commitId
● 還可以創(chuàng)建帶有說明的標(biāo)簽生均,用-a指定標(biāo)簽名,-m指定說明文字: git tag -a 標(biāo)簽名 -m “標(biāo)簽說明” commitId
看標(biāo)簽的文字說明: git show 標(biāo)簽名
刪除標(biāo)簽: git tag -d 標(biāo)簽名
推送某個標(biāo)簽到遠程: git push origin 標(biāo)簽名
一次性推送全部尚未推送到遠程的本地標(biāo)簽: git push origin --tags
刪除遠程標(biāo)簽:
● 先刪除本地標(biāo)簽
● 然后: git push origin :refs/tags/標(biāo)簽名
Sourcetree使用
1 是否展示暫存區(qū)
建議平時使用時候打開暫存區(qū)腥刹,這樣避免一些不想提交的文件马胧,比如一些環(huán)境的配置等直接提交上去
2 merge操作
把目標(biāo)分支合并到當(dāng)前分支
如果你想要合并某一分支的某一提交節(jié)點到當(dāng)前分支,也可以直接使用merge操作衔峰,像下圖那樣佩脊。這樣某個提交節(jié)點之前的所有提交會合并到當(dāng)前分支
3 rebase操作(https://git-scm.com/docs/git-rebase)
使用場景:
變基基礎(chǔ)功能和合并類似,起到分支合并的作用垫卤,而且使用變基操作可以保持當(dāng)前分支提交記錄的整潔性威彰,使我們可以更容易查看分支的提交記錄。未推送過遠端穴肘,或者一個人開發(fā)一個分支歇盼,沒有進行合并操作的情況下,的時候可以放心的在你自己的分支上使用rebase操作评抚。
有時候當(dāng)我們執(zhí)行commit操作之前忘記pull遠端分支會造成旺遮。拉取失敗赵讯,這個時候我們可以勾選上用變基代替合并盈咳,可以讓代碼拉取下來
變基還有一些更加強大耿眉,方便與我們的操作,在下面的交互式變基會詳細講解鱼响,先說下變基的基本操作
變基實現(xiàn)的過程:git會從兩個分支的共同(待變基分支鸣剪,變基到的分支)的第一個提交節(jié)點開始提取待變基(一般是當(dāng)前分支)分支上的修改,然后將待變基分支指向基分支的最新提交丈积,最后將剛才提取的修改應(yīng)用到基分支的最新提交的后面
rebase后
注意事項:盡量在你未推送過遠端的時候才進行rebase操作
● 如果多人開發(fā)同一個分支的時候如果你已經(jīng)push過筐骇,基分支又有改動,這個時候進行rebase操作的時候后江滨,另外一個人在push代碼就會出現(xiàn)錯誤铛纬。
思考總結(jié)meger和rebase:
相同點:都可以進行兩個分支合并
不同點:
● 合并可以保存整個歷史記錄,變基可以創(chuàng)建線性歷史記錄唬滑,難以追溯歷史告唆,可能會造成提交丟失,
● 使用sourcetree解決沖突時候晶密,使用“我的版本”解決沖突擒悬,使用“他人的版本”解決沖突是相反的
● rebase可以讓某一段提交合并到分支上,也可以刪除某各分支上的某一段提交稻艰,等等
meger只能合并某一個提交之前的所有的提交合并到某一個分支上
4 interactive Rebase 操作
使用場景:
● 可以把多次提交合并成一次提交懂牧,比如你調(diào)試某個功能,或者修復(fù)某個bug時候進行了多次提交尊勿,這個時候可以把這些提交合并成一次提交僧凤,保持功能的完整性。
● 修改歷史提交記錄元扔,可以使你的提交看起來更加的友好
● 修改歷史提交順序
● 修改歷史提交躯保,例如將中間的某一次分割成多次提交,保證功能的獨立性
● 刪除歷史提交摇展,比如你提交記錄中的任意某一次提交的功能吻氧,或者修改不想要了,可以使用該功能咏连,和下面的提交回滾比較提交的紀錄也會被刪除盯孙。
這些功能保證提交記錄的整潔性,提高review代碼的效率
更多其他的功能可以使用git命令實現(xiàn)
注意事項:
需要是未push的提交,否者只能強制push(sourcetree設(shè)置成允許強制push祟滴,sourcetree語言設(shè)置為英文時有這個設(shè)置選項)
強制推送可能會導(dǎo)致數(shù)據(jù)丟失振惰,所以在使用它之前,應(yīng)該與團隊成員溝通垄懂,確保你有完整的備份骑晶,確保這個操作是安全的
5 重置提交
把分支重置到某一個提交節(jié)點痛垛,比如:你的分支合并錯了,或者剛提交功能產(chǎn)品不要了桶蛔,提交的bug修改錯誤等等
下面看下具體操作
軟合并:將此次提交回滾到指定提交位置匙头,但這個過程中會將修改過的文件暫存到暫存區(qū)
混合合并:將此次提交回滾到指定的位置,但這個過程中不會將修改過的文件暫存到暫存區(qū)仔雷,而是將修改過的文件存放在工作區(qū)
強行合并:將此次提交回滾到指定的位置蹂析,但這個過程中將直接丟棄之前修改的所有文件
● 回滾本地的提交
根據(jù)實際需求選取合并類型,再點擊確定即可
● 回滾遠程提交(不建議)
注意事項:不建議進行此操作
1.先按照上面回滾本地提交的操作重置到某次提交碟婆,
2.強制push(sourcetree設(shè)置成允許強制push电抚,sourcetree語言設(shè)置為英文時有這個設(shè)置選項)
6 提交回滾(把某一次提交回滾掉,本地遠程都可以)
當(dāng)我們開發(fā)的時候某一次提交的功能竖共,不想要了蝙叛,可以使用這個操作
注意事項:會有提交記錄,和回滾記錄
7 patch
應(yīng)用場景:可以靈活的把某些提交記錄公给,應(yīng)用到其他分支借帘,在某些極端情況下我當(dāng)前分支只想要另一個分支的某幾個提交,比如向測試在我的分支功能上模擬在另一個分支修復(fù)的某個bug妓布,或者是產(chǎn)品是想上線某個分支上的一部分功能姻蚓。避免再人工寫一遍代碼,這樣提高效率匣沼,避免出錯狰挡,和人工再一次修改相比合并代碼的時候,也不會有沖突
● 創(chuàng)建補妒吞巍(生成一個.diff文件)
注意事項:
- 點擊創(chuàng)建前注意選擇好存儲位置
-
可以把多個提交記錄一塊創(chuàng)建補丁
● 應(yīng)用補丁
image20.png
注意點:
sourcetree工作區(qū)或者暫存區(qū)有內(nèi)容時候右鍵該區(qū)域有應(yīng)用補丁的入口加叁,或者通過sourcetree—>動作—>應(yīng)用補丁
8 cherry-pick
應(yīng)用場景:把某些提交記錄,應(yīng)用到其他分支唇撬,和上面的patch使用場景類似
● cherry-pick patch區(qū)別:
cherry-pick 操作比較快捷它匕,patch可以把生成的.diff文件發(fā)送給別人使用,也可以對未提交的改變創(chuàng)建補丁。
● cherry-pick, merge區(qū)別:
merge只能合并某一個提交之前的所有的提交記錄合并到某一個分支上窖认,會把整個分支上的所有修改都合并過來豫柬。cherry-pick可以靈活的操作某一個或者某些提交
9 stash(可以跨分支使用)
使用場景:把暫時不提交的代碼修改存貯下來以便下次使用,比如在某一個分支還沒開發(fā)完的功能暫時存儲下來扑浸,切換到另一個分支緊急開烧给。或者把某些公用的調(diào)試代碼暫存起來在多個分支上使用
10 tag
使用場景: 可以在某個版本發(fā)布后打上標(biāo)簽用于記錄喝噪,如果你在版本打包上線后础嫡,打了tag,發(fā)現(xiàn)審核未通過酝惧,又進行了一些修改榴鼎,這個時候如果版本號沒有變化伯诬,你可以不必刪掉這次tag重新打tag,可以使用下面的移動標(biāo)簽的功能
移動標(biāo)簽功能:(已經(jīng)打好的標(biāo)簽移動提交節(jié)點)
● 在“標(biāo)簽名稱”列中巫财,鍵入要移動的現(xiàn)有標(biāo)簽盗似。
● 在高級選項下,選中“ 移動現(xiàn)有標(biāo)簽 ” 框翁涤。通過點擊下面的按鈕(箭頭指向)指定要移動的提交:
11 checkout
把HEAD指向任何一個提交記錄桥言,以便進行其他操作,比如葵礼,以這個節(jié)點創(chuàng)建新分支
12 存檔
以某個提交節(jié)點把工程存儲到某個文件夾下