① 文件夾A,裡面有一個子文件夾B,B中已經添加過git了,現在我想給A加上git,並且包含B,我應該怎麼做
是否是說通過git init初始化過B目錄?
如果是這個意思,那麼你可以刪除B目錄下的.git目錄,然後在A目錄下再次執行git init,則可以把A/B目錄皆納入git倉庫。
② Git常用命令
1.1 配置環境
當安裝Git後首先要做的事情是設置用戶名稱和email地址。這是非常重要的,因為每次Git提交都會使用該用戶信息。該用戶信息和GitHub上注冊的遠程倉庫的相關信息沒有任何關系。
git config --global user.name "你的名字"
git config --global user.email "你的郵箱"
git config --list
配置信息保存在用戶目錄下的.giitconfig文件中
1.2 獲取Git倉庫
要使用Git對我們的代碼進行版本控制,首先需要獲得Git倉庫
獲取Git倉庫通常有兩種方式:
執行步驟如下:
1、在電腦的任意位置創建一個空目錄作為我們的本地Git倉庫
2、進入這個目錄中,點擊右鍵打開Git bash 窗口
3、執行命令git init
可以通過Git提供的命令從遠程倉庫進行克隆,將遠程倉庫克隆到本地的命令形式為:
git clone 遠程Git倉庫地址
1.3 工作目錄、暫存區以及版本庫概念
版本庫:.git隱藏文件就是版本庫,版本庫存儲了很多配置信息、日誌信息和文件版本信息等
工作目錄(工作區):包含.git文件夾的目錄就是工作目錄,主要用於存放開發的代碼
暫存區:.git文件夾中有很多文件,其中一個index文件就是暫存區,也可以叫做stage。暫存區是一個臨時保存修改文件的地方
1.4 Git工作目錄下文件的兩種狀態
Git工作目錄下的文件存在兩種狀態:
Unmodified 未修改狀態
Modified 已修改狀態
Staged 已暫存狀態
這些文件的狀態會隨著我們執行Git的命令發生變化
1.5 本地倉庫操作
git status 查看文件狀態
也可以使用git status -s使輸出信息更簡潔
git add 將未跟蹤的文件加入暫存區,將已經修改的文件加入暫存區也是通過這個命令
git reset 將暫存區文件取消暫存
git commit -m 「你的說明」 將暫存區文件提交到本地倉庫
git rm 刪除文件 說明:這種操作是直接將文件加入到暫存區裡面,直接提交到本地倉庫生效,而直接刪除的話沒有進入到暫存區,需要先把文件加入到暫存區之後,再提交到本地倉庫。
將文件添加至忽略列表
一般我們總會有些文件無需納入Git的管理,也不希望他們總出現在未跟蹤文件列表。通常這些都是自動生成的文件,比如日誌文件,或者編譯過程中創建的臨時文件等。在這種情況下,我們可以在工作目錄中創建一個名為.gitnore的文件(文件名稱固定),列出忽略的文件模式。下面是一個示例:#代表注釋
由於windows無法創建不含文件名的文件,因此我們需要在bash窗口中用如下命令創建。
git log 查看日記記錄
1.6 遠程倉庫操作
如果想查看已經配置的遠程倉庫伺服器,可以運行git remote 命令。它會列出指定的每一個遠程伺服器的簡寫。如果已經克隆了遠程倉庫,那麼至少可以看見origin,這是Git克隆的倉庫伺服器的默認名字
git remote -v 可以查看對遠程倉庫詳細一點的說明
git remote show origin 可以查看對origin更詳細的遠程倉庫的說明
運行git remote add 添加一個遠程Git倉庫,同時指定一個可以引用的簡寫
如果你想獲得一份已經存在了的Git倉庫的拷貝,這時需要用到 git clone 命令。Git克隆的是Git倉庫伺服器上的幾乎所有數據(包括日誌信息、 歷史 記錄等),而不僅僅是復制工作所需要的文件。當你執行git clone 命令的時候,默認配置下Git倉庫中的每一個文件的每一個版本都將被拉取下來。
如果因為一些原因想要移除一個遠程倉庫,可以使用git remote rm
注意:此命令只是從本地移除遠程倉庫的記錄,並不會影響到遠程倉庫
git fetch 是從遠程倉庫獲取最新版本到本地倉庫,不會自動merge
說明:如果使用fetch命令,拉取的文件會放到版本庫裡面,不會自動整合到工作區,如果需要整合到工作區,需要使用 git merge 遠程倉庫別名/遠程倉庫分支
git pull 是從遠程倉庫獲取最新版本並merge到本地倉庫
注意:如果本地倉庫不是從遠程倉庫克隆,而是本地創建的倉庫,並且倉庫中存在文件,此時再從遠程倉庫中拉取文件的時候會報錯(fatal:refusing to merge unrelated histories),解決此我呢提可以在git pull 命令後加入參數 --allow-unrelated-histories
git push
1.7 Git分支
幾乎所有的版本控制系統都是以某種形式支持分支。使用分支意味著你可以把你的工作從開發主線上分離開來,以免影響開發主線。Git的master是一個特殊分支。它跟其它分支沒有區別。之所以每一個倉庫都有mater分支,是因為git init默認創建它,並且大多數人都懶得去改動它。
# 列出所有本地分支
$ git branch
#列出所有遠程分支
$ git branch -r
#列出所有本地分支和遠程分支
$git branch -a
git branch 分支名稱
git checkout 分支名稱
git push 遠程倉庫別名 遠程倉庫分支
git merge 分支名稱 說明:在當前分支下合並其他分支
注意:如果兩個分支存在同樣的文件名且同行的內容不一樣,那麼會產生矛盾,需要自己手動修改產生矛盾後的文件,然後添加到暫存區然後提交。
git branch -d 分支名稱
如果要刪除的分支中進行了一些開發動作,此時執行上面的刪除命令並不會刪除分支,可以將命令中的-d參數改為-D
如果要刪除遠程倉庫中的分支,可以使用命令git push origin -d branchName
1.8 Git標簽
像其他版本控制系統一樣,Git可以給 歷史 中的某一給提交打上標簽,以示重要。比較有代表性的是人們會使用這個功能來標記發布結點(v1.0、v1.2等)。標簽指的是某個分支某個特定時間點的狀態。通過標簽,可以很方便地切換到標記時的狀態。
#新建一個tag
$ git tag [tagName]
$ git tag
#新建一個分支,指向某個tag
$ git checkout -b [branch] [tag]
#刪除本地tag
$git tag -d[tag]
#刪除遠程tag
$git push origin :refs/tags/[tag]
③ Git上傳文件及文件夾
最近做一批大麥轉錄組數據的分析,考慮到這個物種注釋還不是很完善,所以自己做了一個orgdb的注釋包,傳到github上,供實驗室的師弟和師妹用下。
第一個想到的就是git上傳。
很早之前,就安裝過git並綁定了github賬號,但是一段時間不用,就忘記了。
所以記錄下git建庫及上傳的過程。
首先進入到需要上傳文件的項目文件夾里。(我自己建了個test文件夾)
(如果要上傳文件,那麼進入相應的文件夾里,上傳,如果上傳文件夾,可以直接在當前目錄就行,我自己建了個test.txt文件)
④ git 如何忽略項目中的子文件夾
在使用git tracking 項目文件的變化時,如果項目中包含大的數據文件變化,會佔用大量的空間用於記錄歷史,對於不需要tracking的文件,可以通過以下方法去除git tracking,以節省磁碟空間。
step1: 在git tracking目錄下,簡歷文件,文件名為" .gitignore "。對於windows系統,系統禁止建立該文件名為「 .gitignore 」的文件,可以新建一個文件,重命名為" .gitignore. "
step2: 在文件中添加不需要跟蹤的文件夾,並以'/' 結尾,如:
'excludedFOlder/'
reference: https://www.atlassian.com/git/tutorials/saving-changes/gitignore
注意,gitignor文件的編輯請使用windows自帶notepad,如果某些時候gitignor不工作,使用下面語句清空cache:
git rm -r --cached .
git add .
git commit -m "fixed untracked files"
⑤ Git系列之底層原理篇
本章節是Git的核心知識點,主要是介紹Git底層原理與在使用Git過程中的幾個重要區域,弄懂Git的整個使用流程,以及數據的存儲過程。
工作區(Working Directory):
工作區就是我們平時編寫文本文件的地方
暫存區(Stage/Index):
暫存區是我們提交文本文件到本地倉庫的來源地,只有把工作區的文件添加至暫存區,才可以被提交至本地倉庫。
本地倉庫(Repository):
本地倉庫是保存每次文件更新的記錄,包括提交人,提交時間,提交的內容等詳細信息,方便追溯歷史版本。
遠程倉庫(Remote Repository):
遠程倉庫算是本地倉庫的一個副本,主要是方便合作夥伴之間的倉庫文件同步。
因此它的使用流程可以簡單的概括為:
1、在本地搭建一個目錄,用來創建git倉庫
$ git init gitDirectory
2、在倉庫目錄下創建文本文件(工作區)
$ cd gitDirectory
$ echo "first txt" > first.txt
3、把工作區的first.txt文件添加至git暫存區
$ git add first.txt
4、將暫存區中的文件first.txt提交至本地倉庫
$ git commit -m "first commit"
5、將文件保存至本地倉庫就已經可以記錄我們每次提交的歷史信息了,但是為了方便其他夥伴一起協作,還需要搭建一個遠程服務。(本次以GitHub為例)
在GitHub創建一個和本地一樣名稱的倉庫,創建成功後會生成一個倉庫地址:
https://github.com/mr-kings/gitDirectory.git
6、將本地倉庫和遠程倉庫關聯起來
$ git remote add origin https://github.com/mr-kings/gitDirectory.git
7、第一次將本地倉庫提交至遠程倉庫
$ git push -u origin master
第一次需要添加 -u 參數,即把本地的master分支和遠程倉庫的master分支對應上
8、此時本地倉庫和遠程倉庫就已經實現了同步,其他協作夥伴只需到遠程倉庫把倉庫克隆到自己的電腦即可進行協作編輯
$ git clone https://github.com/mr-kings/gitDirectory.git
9、克隆下來以後會在本地生成本地倉庫以及工作區,後續的操作和2步驟及以後步驟一致
需要注意的是:遠程倉庫有兩種連接方式https/ssh,上面的例子使用的https,其實ssh方式會比https快的多,它還可以通過添加密鑰的方式省去每次提交時都要輸入用戶名和密碼的問題,這里不做詳細介紹。https也是可以通過配置省去每次推送都需要輸入用戶名和密碼的問題。
Git安裝成功後,在本地新建一個Git倉庫,$ git init Gitstudy會生成一個.git文件夾,如果你創建的時候沒有發現.git目錄那應該是你的電腦默認隱藏了.git文件夾,有兩種方式可以查看它:
第一種方式:
命令行工具,在當前目錄下,在命令行里輸入 $ ll -a 即可查看
第二種方式:
在當前目錄下,點擊查看菜單,然後勾選上隱藏的項目即可
.git目錄就是暫存區和本地倉庫的位置,所以它的核心就在這里,下面看看它有哪些內容:
由上圖可知,初始化的時候.git目錄下有以下文件及文件夾:
config(文件):存放當前倉庫的一些配置信息,比如記住用戶名和密碼,別名等
下面是它的常用選項:
[core] ignorecase 是否忽略文件大小寫
[remote "origin"] url 配置遠程倉庫地址
[remote "origin"] fetch 遠程分支映射關系
[user] name 用戶名
[user] email 郵箱
[alias] 命令別名配置 : cmt = commit
description(文件):創建倉庫的描述文件
HEAD(文件):指示當前被檢出(所在)的分支,如當前在test分支,文件內容則為ref: refs/heads/test。
hooks/(文件夾):包含客戶端或服務端的鉤子腳本(hook scripts),如pre-commit,post-receive等
info/ (文件夾):用以存儲一些有關git倉庫的信息,如exclude
objects/ (文件夾):用以存儲git倉庫中的所有數據內容
refs/(文件夾):包含 heads 文件夾,remote文件夾。heads 記錄本地相關的各 git分支操作記錄,remote 記錄遠程倉庫相關的各git分支 操作記錄
當第一次提交的時候還會生成以下文件及文件夾:
index (文件) -- (在git add file的時候生成):是當前版本的文件索引,包含生成當前樹(唯一確定的)對象的所虛信息,可用於快速比對工作樹和其他提交樹對象的差異(各commit和HEAD之間的diff),可用於存儲單文件的多個版本以有效的解決合並沖突。可使用git ls-files 查看index文件內容
COMMIT_EDITMSG(文件) -- (在git commit -m "first commit"的時候生成):最近一次的 commit edit message
logs/ (文件夾) -- (在git commit -m "first commit"的時候生成):放置git倉庫操作記錄的文件夾,包含HEAD文件 和 refs文件夾
以上簡單介紹了.git目錄下的文件及文件夾,重點則是objects文件夾:
經過第一次提交後objects文件夾下多出了3個文件夾:44/、d0/、f6/。通過提交的日誌我們發現,commit後會生成一個40位的16進制字元串(前兩位作為文件夾名稱,後38位為內容哈希值)
官方描述:這是一個 SHA-1 哈希值——一個將待存儲的數據外加一個頭部信息(header)一起做 SHA-1 校驗運算而得的校驗和(前2位作為文件夾名稱 -- 後面38位作為內容的哈希值)
通過cat-file -t sha-1 命令查看當前哈希值所屬的類型:
由圖可知它是一個commit對象
再通過命令cat-file -p sha-1查看該commit對象包含有哪些信息
由圖知一個commit對象包含了tree對象,本地倉庫信息,提交人信息及提交時的備注信息。
再通過上述命令查看tree對象又包含又哪些信息:
由圖知tree對象又包含了blob對象,在多目錄的情況下tree對象還會包含其他tree對象。
由此得出結論:剛才提交的時候生成的那個3個文件夾分別對應的是3個對象即:44/文件夾對應的是commit對象,f6/文件夾對應的是tree對象,d0/文件夾對應的是blob對象。層級關系是:commit對象對應一個tree對象,tree對象可以包含一個或多個其他tree對象和blob對象。
下面就簡單介紹git中的幾個對象:
blob:
blob對象只跟文本文件的內容有關,和文本文件的名稱及目錄無關,只要是相同的文本文件,會指向同一個blob。
tree:
tree對象記錄文本文件內容和名稱、目錄等信息,每次提交都會生成一個頂層tree對象,它可以指向其引用的tree或blob。
commit:
commit對象記錄本次提交的所有信息,包括提交人、提交時間,本次提交包含的tree及blob。
tag:
標簽引用,它指向某一個commit。
用下面的圖可以把今天的內容概括起來:上半部分描述了git的操作流程圖,下半部分描述git底層數據存儲結構圖
Git流程及底層結構圖
下面就對圖的下半部分做個詳細說明:
1、在與.git同級目錄下新建文件夾directory,再在directory目錄下新建一個文本文件first.txt,裡面的內容為1。當執行$ git add first.txt 的時候就會在.git/objects/生成一個blob對象的文件夾(前兩位為文件夾名稱 -- 後38位為文本內容的哈希值)對應上圖的第一個d00491 -- blob對象。
2、當執行$ git commit -m "first commit" 的時候就會在.git/objects/下新生成了2個tree對象和一個commit對象的文件夾(前兩位為文件夾名稱 -- 後38位為文本內容的哈希值)對應上圖的f6589b -- tree對象,4a2e3e -- tree對象,6b18a7 -- commit對象。之所以生成兩個tree對象是因為directory目錄為一個tree對象還有與commit對象一一對應的頂層tree對象。這個時候HEAD游標指向的是當前master分支的first commit。並且在這次提交的時候打個v1.0版本的標簽。
3、在與.git同級目錄下新建一個新的文本文件second.txt,內容為2。當執行$ git add second.txt 的時候就會在.git/objects/生成一個新的blob對象的文件夾(前兩位為文件夾名稱 -- 後38位為文本內容的哈希值)對應上圖的0cfbf0 -- blob對象。
4、當執行$ git commit -m "second commit" 的時候就會在.git/objects/下新生成了1個tree對象和一個commit對象的文件夾(前兩位為文件夾名稱 -- 後38位為文本內容的哈希值)對應上圖的35e40c -- tree對象,d6dca9 -- commit對象。只生成一個與commit對象一一對應的頂層tree對象。由於本次提交directory目錄下的first.txt內容沒有變化,所以上圖的35e40c -- tree對象還會指向f6589b -- tree對象。這個時候HEAD游標指向的是當前master分支的second commit(HEAD索引向前移動),second commit 會指向上一次的提交即 parent指向first commit。
後續的操作以此類推,但需要注意的點是:
1、blob對象只對文件的內容有關,和文件名稱無關,如果不同的文件名稱,內容相同只會有一個blob對象,生成的新tree對象會指向該blob對象。例如上圖的third.txt和four.txt裡面的內容都為3。所以不會生成新的blob對象,新的tree對象只會指向同一個blob。
2、如果每次提交的時候包含的某些文件並沒有改動(更新),那麼就會直接指向它原來的索引,不會重新生成。例如上圖的directory/first.txt,second.txt
3、每次commit對象都會和頂層的tree對象一一對應。
⑥ Git 進階 - 子倉庫 subtree
問題實例(真實訴求)
一個工具類庫,有以下兩個目標:
如果直接使用 Git 管理這個lib 添加到這個項目來呢,單獨維護。可能就會出現每一次更新 repo 就要更新多個 repo 的情況。對於有很多開發協同者來說,簡直是災難。
git subtree 是什麼?
git subtree 可以實現 一個倉庫作為其他倉庫的子倉庫 ,能夠相對較好的解決上面兩難問題。
有個和 git subtree 概念類似的功能 git submole ,雖然都沒有用過,但目前來看 git subtree 比 git submole 更加強大,是可以替代 submole 的方案。
subtree 的作用就是可以實現一個倉庫作為其他倉庫的子倉庫,對於主項目來說,另一個項目只作為主項目的一個子目錄而存在。
圖片來自 : https://segmentfault.com/a/1190000012002151
創建一個git repo GitStudy
創建一個 lib repo commonToolsCopy
使用 subtree 命令,將 tools 放到 gitStudy 目錄下(作為lib)
下面 commonTools
上面命令執行後,就可以將 commonTools 倉庫中 master 上的更新更新到本地
之後會生成兩條日誌信息
添加之後 commonTools 就是主項目的一個普通文件夾,如果這時候 commonTools 內容更新之後,正常 git push 即可,子項目對於主項目來說完全是透明的。
在主項目 git push 之後,對子項目修改的內容是不會直接更新到子項目自身的
需要執行 git subtree pull
如果單獨對子項目做了更新,主項目就需要手動更新下了
執行之後,仍然會在主項目中生成相關的 commit 記錄
在 subtree 相關命令經常會用到 <repository> 每次都寫地址還是比較麻煩,這里可以用 git remote 命令簡化寫法,為這個遠程地址定義一個 「別名」
比如使用 subtree push 的時候就可以使用如下命令
在添加 subtree 的時候是指定了分支的,如果要切換分支直接移除 subtree,重新加入子項目的分支
驗證1:其他人 clone 該項目對 sub repo是無感知的
驗證2:在主項目中修改 sub repo 的內容 push,在 app 中會形成 commit 在 sub repo 中不會有 commit
驗證3:使用一下命令,可以push 到 sub repo 中 推送修改到源倉庫
驗證4:直接在 sub repo 項目中更新內容
那麼 main repo 需要還是需要 pull 一下 從源倉庫拉取更新
非原理性提示 不加 --squash 不可以,
在 pull 的過程中可能需要處理沖突
驗證5:修改的內容同時包含主項目和子項目, 使用 git push 再使用 git subtree push 會做挑揀,但如果混雜的內容很多的話,這個過程也會變得復雜,so 建議 盡可能分開提交,減少這種沖突。
https://segmentfault.com/a/1190000012002151
http://einverne.github.io/post/2020/04/git-subtree-usage.html
⑦ git submole
添加後會多一個 .gitmoles 文件,文件的內容只是保存submole的引用信息,包括路徑和repo地址
添加完後需要在主項目 git commit 提交新增子項目文件夾以及 .gitmoles 文件的修改
在子項目加入到項目的時候,其實做了這樣三件事:
所以在當前項目push到remote repository的時候,只是更新了引用的 commit id ,那麼在其他人clone項目的時候,就可以獲取子項目的 commit id ,然後在 git submole update 的時候獲取子項目 commit id 所表示的commit
查看子模塊的commit id,如果子模塊沒有被checkout,前面會有 - ,那麼就需要 git submole init , git submole update
clone帶有submole的項目的兩種方法:
其實相當於
注意,在clone之後, cd submole/ ,然後 git status ,你會看到這樣的狀態
也就是說,現在是 detached HEAD ,使用 git branch 就可以查看到
所以需要 git checkout master 到master分支,然後在master分支上修改
為什麼呢?因為父項目不記錄子模塊的修改,只記錄commit id,所以clone的時候只獲取到對應的commit,而不在任何分支上,但是master分支的commit id和HEAD保持一致,所以只要 git checkout master ,而不需要新建分支
注意: 只有子項目內容更新,就需要更新父項目引用的子項目的commit id
其實子項目和父項目只是獨立的git項目,所以其他操作和一般git項目一樣,在子項目修改,需要
其實普通的git項目一樣操作,然後需要在父項目更新引用的子項目commit id,有 兩 一種方法:
為什麼這種方法不行呢,其實是個坑!就是你 git submole update 之後,你的子項目會恢復到你父項目引用的那個commit,也就是不是最新的commit,此時 git status 是干凈的,就像第一次 git clone 項目然後 git submole init , git submole update 一樣,子項目指向的是父項目引用的那個commit,所以此時把子項目 git checkout master 之後,再切回到父項目,使用 git status ,你會發現提示子項目有新的commit,所以還是需要父項目更新引用的子項目的commit id
注意: 如果更新submole的時候有新的commit id產生,需要在父項目產生一個提交,用來更新對子項目commit id的引用
兩種方法:
子項目一旦產生變動,有新的commit id,父項目必需產生一個提交,更新對子項目commit id的引用
Git Submole使用完整教程
使用Git Submole管理子模塊
Git submole的坑
⑧ Git撤銷與合並
1. git init
創建一個空的git repo,也就是創建一個.git的子目錄,這個目錄包含了幾乎所有git存儲和操作的東西。新初始化的.git目錄的典型結構如下:
description文件僅供git web程序使用,平常無需關心。
config文件包含項目特有的配置選項。
info目錄包含一個全局性排除文件,用以放置那些不希望被記錄在.gitignore文件中的忽略模式。
hooks目錄包含客戶端或服務端的鉤子腳本。
HEAD文件指向目前被檢出的分支。
index文件(尚待創建)保存暫存區信息。
objects目錄存儲所有數據內容。
refs目錄存儲指向數據的提交對象的指針。
git的默認分支名字是master,git init時默認創建它。
2. git的三種狀態,以及工作區(Working directory),暫存區(Index),HEAD
Git 有三種狀態,你的文件可能處於其中之一:已修改(modified)、已暫存(staged)和已提交(committed)
基於剛才init的git project,做一些改動。
會看到在git add之後,.git下面多了一個index文件。
這時候,所做的改動就處於已暫存狀態,體現在index文件中。
可以利用以下命令查看git緩存了的內容。
同時,.git/objects下面多了一個子文件夾,並生成了一個新文件。這個新文件就對應了剛才所做的改動。這就是git存儲內容的方式--一個文件對應一條內容,以該內容加上特定頭部信息一起的SHA-1校驗和作為文件名。校驗和的前兩個字元用於命名子目錄,餘下的38個字元則作為文件名。後面會詳敘。
可以通過cat-file命令從git那裡查看存儲的內容。
git cat-file -p
由於file1.txt的內容為空,所以這里顯示為空。
這時候可以往file1.txt里添加一些內容,並git add。可以看到.git/objects又多了一個object。
查看這個新的對象的內容以及類型。會發現它是一個blob對象。
接下來commit這個change。
myProject $ git commit -m "first commit"
查看這個commit 對象的類型以及內容,commit的tree對象所指向的內容, 我們會發現,這個tree指向的是一個blob,而這個blob的內容,就是我們剛剛做過改動的文件。
同時,我們查看一下暫存區的內容:
會發現,暫存區指向的也是同樣的blob對象。
至此,一個commit就提交了,工作區,暫存區,以及head又指向了同樣的內容。
它們更新內容的順序為,工作區->暫存區->head
3. git reset
將做過的change撤銷掉,就像沒有發生過一樣。
git reset 應用的順序為 head->暫存區->工作區。
(1) git reset --soft
當前,git的狀態如下。
head指向的內容為:
(head是當前分支引用的指針,總是指向該分支上的最後一次提交。)
index指向的內容為:
(索引是你的預期的下一個提交)
我們來進行一次reset。(移動HEAD, --soft)
--soft將僅僅移動HEAD的指向,而並不會移動index以及工作區。
HEAD 指的是HEAD的父節點。HEAD 是父節點的父節點,也可以寫成HEAD 2.
所以這個命令本質上是撤銷了上一次git commit命令。
(2) git reset --mixed
接下來,再通過reset來更新索引。(--mixed,默認行為)
(3) git reset --hard
reset更新工作目錄(--hard)
git reset --hard HEAD~
--hard標記是reset命令的危險用法,它也是git會真正銷毀數據的幾個操作之一。
如果這個commit已經被推送到遠端,可以用這個命令使遠端也回退到相應的版本。
git push origin <branch> --force
4. git revert
將做過的change撤銷掉,通過「反做」某一個版本,用一個新的commit來消除做過的change。
當前git的狀態:
revert其中一個commit:
再來看,多了一個commit,也就是用來revert的commit:
而若是想要revert某個版本,但是在這個版本後又做過change,則在revert的過程中可能出現沖突,則需要解決沖突之後再提交。
5. git merge 與git rebase
先來講講git merge。
當前master 和 dev branch:
接下來打算將dev的工作並入master分支。
另外,還想將master的工作也並入dev。
git merge之後,會發現dev branch指向了與master相同的commit:
所以,git merge是把兩個分支的最新快照,以及兩者最近的共同祖先進行三方合並,合並的結果是生成一個新的快照。
接下來,用git rebase來合並分支。
當前的git狀態
此時,採用git rebase,將dev的工作並入到master。
當在master branch上執行git rebase dev的時候,實際發生的事情是,找到master和dev兩個分支的最近共同祖先,對比當前分支(master分支)相對於該祖先的歷次提交,提取相應的修改並存為臨時文件,然後將master分支指向目標基底(dev的head指向的commit),最後以此將之前另存為臨時文件的修改依序應用。
可以看到,rebase使得提交歷史更加整潔。盡管實際的開發工作是並行在不同branch上進行的,但是它們看上去就像是串列的一樣,提交歷史是一條直線沒有分叉。
因此,變基是將一系列提交按照原有次序依次應用到另一分支上,而合並是把最終結果合在一起。這兩種方式,整合的最終結果所指向的快照始終是一樣的,只不過提交歷史不同。
⑨ git的文件系統與底層原理
由於工作中使用git作為版本管理,之前對git的了解不多,特別是底層方面的原理方面的知識。為了能更好的使用git,有必要學習並梳理下相關知識。
步入正題:
執行git init 初始化後,會在.git文件夾下會創建多個目錄,每個文件夾功能劃分的很清晰。
Git 是一套內容定址文件系統.通過鍵值對的方式存儲和查找。
下面操作一遍,直觀的看到整個過程,以便理解。
參考: https://git-scm.com/docs/git-hash-object
參考: http://man.linuxde.net/find
可以見到文件名稱為數字和字母組成的字元串。這個是根據文件內容和頭信息(Header),通過SHA-1演算法計算得出的40位十六進制校驗和。
SHA-1是一種加密哈希函數(cryptographic hash function)。SHA-1將文件中的內容通過其hash演算法生成一個160bit的報文摘要,即40個十六進制數字(每個十六進制數字佔4位)。它幾乎可以保證,如果兩個文件的SHA-1值是相同的,那麼它們確是完全相同的內容(類似於生活中的指紋識別);SHA-1主要有兩種用途,一個是加密,一個是數據完整性校驗。Linux kernel開創者和Git的開發者——Linus說,Git使用了SHA-1並非是為了安全性,而是為了數據的完整性。理論上SHA-1會在2^51攻擊下實現哈希碰撞,所以也不是完全的安全。
參考: https://git-scm.com/docs/git-cat-file
模擬bolb對象存儲流程
以上,說明了git的數據存儲的基本方式。主要步驟:
下面是創建文件,修改文件,恢復文件的相關過程。
git會記錄每個版本的修改,根據校驗和可恢復到相應的版本。
小結: 這個過程中包括文件創建、文件修改、文件恢復,跟我們平時工作中使用的高級命令功能很相似。git會把整個過程轉化為底層操作,同時對用戶透明。
相關引用參考:
http://smilejay.com/2012/08/git-commit-sha-1/
https://git-scm.com/book/zh/v1/Git-%E5%86%85%E9%83%A8%E5%8E%9F%E7%90%86-Git-%E5%AF%B9%E8%B1%A1
⑩ 如何在Windows系統中創建並使用Git倉庫
Git是用來管理文件版本的軟體,使用它之前需要先創建倉庫。那麼在Windows系統中如何創建Git倉庫呢?下面我給大家分享一下。
Git Bash
首先點擊Windows的開始菜單,在彈出的界面中選擇Git Bash選項,如下圖所示
接下來進入到Git的命令行界面中我們用pwd命令先查看一下當前的路徑,如下u圖所示
接著用cd命令進入到要建倉庫的磁碟,注意不要在C盤建立倉庫,如下圖所示
然後我們在磁碟下面用mkdir命令創建一個倉庫文件夾,如下圖所示
接下來我們進入倉庫文件夾,通過git init命令對倉庫進行初始化,如下圖所示
然後我們打開倉庫文件夾,這時你會看到文件夾下面多了一個git文件夾,這就代表此文件夾是git倉庫文件夾,如下圖所示
接著我們在Git倉庫文件夾下面建立一個txt文本文件,並在文件中寫入一些內容,如下圖所示
最後我們回到Git Bash命令行,運用git add 和git commit命令對文件進行添加並提交即可,如下圖所示