本文已經收錄到Github倉庫,歡迎大家圍觀、star。此倉庫用於分享Java核心知識,包括Java基礎、MySQL、SpringBoot、Mybatis、Redis、RabbitMQ等等,面試必備。
github地址:https://github.com/Tyson0314/Java-learning
如果github訪問不了,可以訪問gitee倉庫。
Git 簡介
Git 是一個開源的分散式版本控制系統,可以有效、快速的進行專案版本管理。Git 是 Linus Torvalds 為了幫助管理 Linux 核心開發而開發的一個開放原始碼的版本控制軟體。
Git工作流程
Git工作流程如下:
- 從遠端倉庫中克隆資源作為本地倉庫;
- 在本地倉庫中進行程式碼修改;
- 在提交本地倉庫前先將程式碼提交到暫存區;
- 提交修改,提交到本地倉庫。本地倉庫中儲存修改的所有歷史版本;
- 在需要和團隊成員共享程式碼時,可以將修改的程式碼push到遠端倉庫。
Git 的工作流程圖如下:
圖片來源:https://blog.csdn.net/ThinkWon/article/details/94346816
儲存原理
Git 在儲存專案狀態時,它主要對全部檔案製作一個快照並儲存這個快照的索引,如果檔案沒有被修改,Git 不會重新儲存這個檔案,而是隻保留一個連結指向之前儲存的檔案。
Git 快照
快照就是將舊檔案所佔的空間保留下來,並且儲存一個引用,而新檔案中會繼續使用與舊檔案內容相同部分的磁碟空間,不同部分則寫入新的磁碟空間。
三種狀態
Git 的三種狀態:已修改(modified)、已暫存(staged)和已提交(committed)。已修改表示修改了檔案,但還沒儲存到資料庫。已暫存表示對一個已修改檔案的當前版本做了標記,使之包含在下次提交的快照中。已提交表示資料已經安全的儲存到本地資料庫。
基本的 Git 工作流程:在工作目錄修改檔案;暫存檔案,將檔案快照放到暫存區域;提交更新到本地庫。暫存區儲存了下次將要提交的檔案列表資訊,一般在 Git 倉庫目錄中。
圖片來源:
https://img2018.cnblogs.com/blog/1252910/201907/1252910-20190726163829113-2056815874.png
配置
設定使用者名稱和郵箱地址:
git config --global user.name "dabin"
git config --global user.email [email protected]
如果使用了 --global 選項,那麼該命令只需要執行一次,因為之後無論你在該系統上做任何事情,Git 都會使用那些資訊。 當你想針對特定專案使用不同的使用者名稱稱與郵件地址時,可以在那個專案目錄下執行沒有 --global 選項的命令來配置。
檢視配置資訊:git config --list
檢視某一項配置:git config user.name
獲取幫助
獲取 config 命令的手冊:git help config
Git 基礎
獲取 Git 倉庫
在現有目錄中初始化倉庫:進入專案目錄並輸入git init
克隆現有的倉庫:git clone https://github.com/...
檔案狀態
檢視檔案狀態:git status
圖片來源:
https://img2018.cnblogs.com/blog/1252910/201907/1252910-20190726163854195-886320537.png
狀態簡覽:
新新增的未跟蹤檔案前面有 ?? 標記,新新增到暫存區中的檔案前面有 A 標記,修改過的檔案前面有 M 標記,如下圖,MM Rakefile
出現兩個M,其中出現在靠左邊的 M 表示該檔案被修改了並放入了暫存區,出現在右邊的 M 表示該檔案被修改了但是還沒放入暫存區。
$ git status -s
M README # 右邊的 M 表示該檔案被修改了但是還沒放入暫存區
MM Rakefile # 左邊的 M 表示該檔案被修改了並放入了暫存區;右邊的 M 表示該檔案被修改了但是還沒放入暫存區
A lib/git.rb # A表示新新增到暫存區中的檔案
?? LICENSE.txt # ??表示新新增的未跟蹤檔案
配置別名
有些人可能經常敲錯命令,通過配置別名可以簡化命令:
通過命令 git config --global alias.st status
將 git status
簡化為 git st
:
$ git config --global alias.st status
$ git st
On branch master
Your branch is up to date with 'origin/master'.
nothing to commit, working tree clean
工作區
檢視工作區修改:git diff
$ git diff
diff --git a/md/leetcode刷題筆記.md b/md/leetcode刷題筆記.md
deleted file mode 100644
index 63a7c90..0000000
--- a/md/leetcode刷題筆記.md
+++ /dev/null
撤銷工作區修改:git checkout -- file_name
,會撤銷工作區的修改,不可恢復,不會撤銷暫存區修改。
撤銷修改還可以使用 restore 命令(git2.23版本引入)。
git restore --worktree demo.txt //撤銷檔案工作區的修改
git restore --staged demo.txt //撤銷暫存區的修改,將檔案狀態恢復到未add之前
git restore -s HEAD~1 demo.txt //將當前工作區切換到上個 commit 版本,-s相當於--source
git restore -s hadn12 demo.txt //將當前工作區切換到指定 commit id 的版本
暫存區
通過git add filename
將工作區的檔案放到暫存區。
git add README.md
檢視暫存區修改:git diff --staged
。可以看到暫存區中有 README.md 檔案,說明README.md檔案被放到了暫存區。
$ git diff --staged
diff --git a/README.md b/README.md
index ecd6c7a..653f001 100644
--- a/README.md
+++ b/README.md
撤銷暫存區修改/unstage:git reset HEAD file_name
,將檔案修改移出暫存區,放到工作區。
git reset 加上 --hard 選項會導致工作目錄中所有修改丟失。
提交
任何未提交的修改丟失後很可能不可恢復。提交命令:git commit -m "add readme.md"
git commit -a -m "xxx"
相當於git add
和git commit -m "xxx"
,將 tracked 的檔案直接提交。untracked 的檔案無法使用此命令直接提交,需先執行 git add 命令,再執行 git commit。
單獨執行git commit
,不帶上-m引數,會進入 vim 編輯器介面:
此時應該這麼操作:
- 按下字母鍵
i
或a
或o
,進入到可編輯狀態 - 輸入commit資訊之後,按下
Esc
鍵就可退出編輯狀態,回到一般模式 - 輸入:wq (儲存退出)或 :wq!(強行退出,不儲存)
修改commit資訊
如果提交後發現漏掉某些檔案或者提交資訊寫錯,使用git commit --amend
重新提交:
git commit -m 'initial commit'
git add forgotten_file
git commit --amend
檢視提交歷史
git log
列出所有提交的更新。
git log -p -2
,-p 用來顯示每次提交的內容差異,-2表示顯示最近兩次提交。
git log --stat
每次提交下面都會列出所有被修改的檔案、有多少檔案被修改和哪些行被修改等。
git log --pretty=oneline
將每個提交放在一行顯示。
git log --pretty=format:"%h %s" --graph
format 表示格式化輸出,%h 提交物件的簡短雜湊串,%s 是提交說明,--graph 可以更形象的展示分支、合併歷史。
$ git log --pretty=format:"%h %s" --graph
* 75f8b36 update
* cd72e4f 刪除查詢效能優化
* 6bddc95 MySQL總結整理
* f8ace0e java常見關鍵字總結
* 0c4efeb 刪除android
* 4844de5 mysql執行計劃
* 635c140 redis分散式鎖
* 7b65bc3 update
* e563eec update
* 67e1cf7 update readme
* 218f353 調整目錄結構
* 9428314 整理Java基礎內容
git log --since=2.weeks
按照時間作限制。
版本回退
版本回退使用git reset
命令。
git reset --hard commit_id
git reset --hard HEAD^ # 回退所有內容到上一個版本
git reset --hard HEAD^^ # 回退所有內容到上上一個版本
git reset --hard HEAD~100 # 回退到之前第100個版本
git reset HEAD readme.txt # 把暫存區的修改撤銷掉(unstage), 重新放到工作區
stash
將未提交的修改儲存起來。用於後續恢復當前工作目錄。
git stash
git stash pop stash@{id} //恢復後刪除
git stash apply stash@{id} //恢復後不刪除,需手動刪除
git stage drop
git stash list //檢視stash 列表
git stash show -p stash@{0} //檢視stash具體內容,-p檢視diff,stash@{0}可以省略
rm和mv
git rm readme.md
:檔案未被修改過,從暫存區移除檔案,然後提交,相當於 rm readme.md
和git add .
。如果只是簡單地從工作目錄中手工刪除檔案,執行 git status 時就會在 “Changes not staged for commit”。
git rm --cached README.md
:讓檔案保留在工作區,但是不想讓 Git 繼續跟蹤。可以使用 --cached 選項來實現。檔案被修改過,還沒有放進暫存區,則必須要用強制刪除選項 -f ,以防止誤刪還沒有新增到暫存區的資料,這樣的資料不能被 Git 恢復。
git rm 支援正則表示式:git rm log/\*.log
。
對檔案改名:git mv README.md README
相當於執行一下三條命令:
mv README.md README
git rm README.md
git add README
忽略檔案
.gitignore 只能忽略未跟蹤狀態的檔案。
如果遠端倉庫已經有了logs資料夾,git rm --cached logs/xx.log
可以刪除檔案的跟蹤狀態,此時本地工作區修改還在。然後更新 .gitignore 檔案,最後git add . & git commit -m "xx" & git push
就可以刪除遠端倉庫對應的檔案。
skip-worktree和assume-unchanged
skip-worktree:
git update-index --skip-worktree [file]
可以實現修改本地檔案不會被提交,但又可以拉取最新更改的需求。適用於一些不經常變動,但是必須本地化設定的檔案。取消skip-worktree:
git update-index --no-skip-worktree [file]
檢視 skip-worktree 列表:
git ls-files -v | grep '^S\ '
。
assume-unchanged:
git update-index --assume-unchanged [file]
該命令只是假設檔案沒有變動,使用reset時,會將檔案修改回去。當遠端倉庫相應的檔案被修改時,pull更新之後,--assume-unchanged 會被清除。取消忽略:
git update-index --no-assume-unchanged file/path
檢視忽略了哪些檔案:
git ls-files -v | grep '^h\ '
遠端倉庫
遠端倉庫是指託管在網路中的專案版本庫。
檢視遠端倉庫
檢視遠端倉庫地址:
$ git remote -v
origin https://github.com/schacon/ticgit (fetch)
origin https://github.com/schacon/ticgit (push)
新增遠端倉庫
執行 git remote add <shortname> <url>
新增遠端 Git 倉庫,同時指定一個簡寫名稱。
git remote add pb https://github.com/paulboone/ticgit
如上命令,可以在命令列中使用字串 pb 來代替整個 URL。如git fetch pb
。
如果使用 clone 命令克隆了一個倉庫,命令會自動將其新增為遠端倉庫並預設以 origin 為預設簡寫名稱。
取消關聯Git倉庫 git remote remove origin
如果想要給origin設定兩個遠端倉庫地址(git add會報錯),可以使用git remote set-url --add origin url
來設定。
$ git remote add origin xxx.git
fatal: remote origin already exists.
$ git remote set-url --add origin xxx.git
#success
修改遠端倉庫
修改遠端倉庫地址:
git remote set-url origin [email protected]:Tyson0314/Blog.git
pull 和 fetch
從遠端倉庫獲取資料:git fetch [remote-name]
git fetch 命令將資料拉取到本地倉庫,但它並不會自動合併到本地分支,必須手動將其合併本地分支。
git pull 通常會從遠端倉庫拉取資料並自動嘗試合併到當前所在的分支。
git pull = git fetch + git merge FETCH_HEAD
git pull --rebase = git fetch + git rebase FETCH_HEAD
本地倉庫上傳git伺服器
git init # 將目錄變成本地倉庫
git add .
git commit -m 'xxx' # 提交到本地倉庫
git remote add origin https://github.com/Tyson0314/profile # 關聯遠端倉庫
git branch --set-upstream-to=origin/master master # 本地分支關聯遠端分支
git pull origin master --allow-unrelated-histories # 允許合併不相關的歷史
git push -u origin master # 如果當前分支與多個主機存在追蹤關係,則-u會指定一個預設主機,這樣後面就可以不加任何引數使用git push。
推送到遠端倉庫
推送使用命令:git push [remote-name] [branch-name]
git push origin master
檢視遠端倉庫
git remote show origin
遠端倉庫移除和命名
移除遠端倉庫:
git remote rm paul
重新命名遠端倉庫:
git remote rename old-name new-name
標籤
給歷史的某個提交打標籤,如標記釋出節點(v1.0等)。
tag標籤可以幫助我們回退到某個版本的程式碼,我們通過tag的名稱即可回退,而不需要根據某個提冗長的commit ID來回退:
- 檢視本地tag:git tag
- 新建tag:git tag -a v2.0 -m 'msg'
- 推送指定tag至遠端:git push origin v2.0
- 推送本地所有tag至遠端:git push origin --tags
- 刪除本地tag:git tag -d v2.0
- 刪除遠端tag:git push origin --delete tag 2.0
- 本地檢視不同tag的程式碼:get checkout v1.0
- 檢視標籤詳情(包含commitId):
git show v1.0
- 回退到某個版本:git reset --hard commitId
- 獲取遠端分支:git fetch origin tag V2.0
建立標籤
Git 使用兩種主要型別的標籤:輕量標籤(lightweight)與附註標籤(annotated)。一個輕量標籤很像一個不會改變的分支 - 它只是一個特定提交的引用。然而,附註標籤是儲存在 Git 資料庫中的一個完整物件。 它們是可以被校驗的;其中包含打標籤者的名字、電子郵件地址、日期時間;還有一個標籤資訊;並且可以使用 GNU Privacy Guard (GPG)簽名與驗證。 通常建議建立附註標籤。
建立的標籤都只儲存在本地,不會自動推送到遠端。
附註標籤
git tag -a v1.4 -m 'my version 1.4'
-m 選項指定了一條將會儲存在標籤中的資訊。
使用 git show v1.4 命令可以看到標籤資訊與對應的提交資訊。
輕量標籤
git tag v1.4-tyson
此時執行 git show v1.4-tyson
不會看到額外的標籤資訊,只顯示提交資訊。
推送標籤
推送某個標籤到遠端,使用命令git push origin <tagname>
一次性推送全部尚未推送到遠端的本地標籤 git push origin --tags
刪除遠端標籤(先刪除本地標籤) git push origin :refs/tags/<tagname>
後期打標籤
比如給下面的這個提交( modified readme.md
)打標籤: git tag -a v1.2 c1285b
$ git log --pretty=oneline
22fb43d9f59b983feb64ee69bd0658f37ea45db6 (HEAD -> master, tag: v1.4-tyson, tag: v1.4) add file note.md
aab2fda0b604dc295fc2bd5bfef14f3b8e3c5a98 add one line
c1285bcff4ef6b2aefdaf94eb9282fd4257621c6 modified readme.md
ba8e8a5fb932014b4aaf9ccd3163affb7699d475 renamed
d2ffb8c33978295aed189f5854857bc4e7b55358 add readme.md
共享標籤
git push 命令並不會傳送標籤到遠端倉庫伺服器上。在建立完標籤後你必須顯式地推送標籤到共享伺服器上:git push origin v1.5
把所有不在遠端倉庫伺服器上的標籤全部傳送到那裡:git push origin --tags
檢出標籤
如果你想要工作目錄與倉庫中特定的標籤版本完全一樣,可以使用 git checkout -b [branchname] [tagname]
在特定的標籤上建立一個新分支:
$ git checkout -b version2 v2.0.0
Switched to a new branch 'version2'
git 別名
取消暫存別名:git config --global alias.unstage 'reset HEAD --'
最後一次提交:git config --global alias.last 'log -1 HEAD'
git 分支
Git 鼓勵在工作流程中頻繁地使用分支與合併。
Git 儲存的不是檔案的變化或者差異,而是一系列不同時刻的檔案快照。git 提交物件會包含一個指向暫存內容快照的指標。
分支建立
$ git branch testing
檢視遠端分支:git branch -r
分支切換
使用 git checkout branch-name
切換分支:
git checkout testing
檢視各個分支當前所指的物件:git log --oneline --decorate
$ git log --oneline --decorate
22fb43d (HEAD -> master, tag: v1.4-tyson, tag: v1.4, tyson) add file note.md
aab2fda add one line
c1285bc (tag: v1.2) modified readme.md
ba8e8a5 renamed
d2ffb8c add readme.md
master 和 tyson 分支都指向校驗和為 22fb43d 的提交物件。
$ git checkout -b iss53
相當於 git branch iss53
加上 git checkout iss53
分支合併
合併 iss53 分支到 master 分支:
git checkout master
git merge iss53
squash merge:合併多個 commit 為一個,合併完需要重新提交,會修改原 commit 的提交資訊,包括 author。
合併衝突
當合併產生衝突時不會自動地建立一個新的合併提交。 Git 會暫停下來,等待你去解決合併產生的衝突。 你可以在合併衝突後的任意時刻使用 git status 命令來檢視那些因包含合併衝突而處於 unmerged 狀態的檔案。
<<<<<<< HEAD:index.html
<div id="footer">contact : [email protected]</div>
=======
<div id="footer">
please contact us at [email protected]
</div>
>>>>>>> iss53:index.html
在你解決了所有檔案裡的衝突之後,對每個檔案使用 git add 命令來將其標記為衝突已解決。然後輸入 git commit -m "merge branch iss53"
完成合並提交。
rebase
現在我們有這樣的兩個分支,test和master,提交如下:
D---E test
/
A---B---C---F--- master
在master執行git merge test,會生成額外的提交節點G:
D--------E
/ \
A---B---C---F----G--- test, master
在master執行git rebase test,本地提交以補丁形式打在分支的最後面:
A---B---D---E---C‘---F‘--- test, master
merge操作會生成一個新的節點,之前的提交分開顯示。
而rebase操作不會生成新的節點,是將兩個分支融合成一個線性的提交。
合併commit:git rebase -i
pick c38e7ae rebase content
s 595ede1 rebase
# Rebase 8824682..595ede1 onto 8824682 (2 commands)
#
# Commands:
# p, pick = use commit
# r, reword = use commit, but edit the commit message
# e, edit = use commit, but stop for amending
# s, squash = use commit, but meld into previous commit
# f, fixup = like "squash", but discard this commit's log message
# x, exec = run command (the rest of the line) using shell
# d, drop = remove commit
s 595ede1 rebase
會將595ede1合到前一個commit,按下:wq
之後會彈出對話方塊,合併commit message。
刪除分支
刪除本地分支:git branch -d iss53
刪除遠端分支:git push origin --delete master
分支管理
得到當前所有分支的一個列表:
$ git branch
* master
tyson
*代表當前 HEAD 指標所指向的分支。
檢視每一個分支的最後一次提交:
$ git branch -v
* master 22fb43d add file note.md
tyson 22fb43d add file note.md
檢視哪些分支已經合併到當前分支:
$git branch --merged
iss53
*master
檢視所有包含未合併工作的分支:
$git branch --no-merged
testing
如果分支包含未合併的工作,使用 git branch -d testing
刪除時會出錯,可以使用 git branch -D testing
強制刪除。
遠端分支
推送
git push origin master
將本地的 master 分支推送到遠端倉庫 origin/master 分支。git push origin tyson:tyson-branch
將本地的 tyson 分支推送到遠端倉庫的 tyson-branch 分支。
假如當前本地分支是 tyson,抓取遠端倉庫資料後,需要進行合併:
git fetch origin
git merge origin/tyson
將本地的所有分支都推送到遠端主機:git push -all origin
強制推送:git push --force origin
跟蹤分支
$ git checkout --track origin/tyson
Branch tyson set up to track remote branch tyson from origin.
Switched to a new branch 'tyson'
本地分支與遠端分支設定為不同名字:
$ git checkout -b tyson-branch origin/tyson
Branch tyson-branch set up to track remote branch tyson from origin.
Switched to a new branch 'tyson-branch'
設定已有的本地分支跟蹤一個剛剛拉取下來的遠端分支,使用 -u 或 --set-upstream-to 選項:
git branch -u origin master
檢視設定的所有跟蹤分支:
$ git branch -vv
iss53 7e424c3 [origin/iss53: ahead 2] forgot the brackets
master 1ae2a45 [origin/master] deploying index fix
* serverfix f8674d9 [teamone/server-fix-good: ahead 3, behind 1] this should do it
testing 5ea463a trying something new
這些資料是本地快取的伺服器資料,如果需要最新的資料,可以先執行:git fetch --all
然後再執行:git branch -vv
fetch和pull
git fetch 會將遠端倉庫的更新拉取到本地遠端倉庫的副本,不會自動合併到本地倉庫。
git fetch 步驟:
git fetch origin master:tmp //在本地新建一個tmp分支,並將遠端origin倉庫的master分支程式碼下載到本地tmp分支
git diff tmp //來比較原生代碼與剛剛從遠端下載下來的程式碼的區別
git merge tmp//合併tmp分支到本地的master分支
git branch -d tmp//如果不想保留temp分支 可以用這步刪除
git pull
= git fetch
+ git merge
刪除遠端分支
git push origin --delete tyson
Git 伺服器會保留資料一段時間,誤刪的遠端分支很容易恢復。
建立遠端分支
基於本地分支建立遠端分支:git push origin backup_foreign:backup_foreign
本地新分支和遠端新分支關聯:git push --set-upstream origin backup_foreign
cherry-pick
參考自:cherry-pick
可以用於將在其他分支上的 commit 修改,移植到當前的分支。
git cherry-pick <commit-id>
當執行完 cherry-pick 之後,將會自動生成一個新的 commit 進行提交,會有一個新的 commit ID,commit 資訊與 cherry-pick 的 commit 資訊一致。遇到衝突則解決衝突,然後 git add 產生衝突的檔案
,然後使用 git cherry-pick --continue
繼續。這個過程中可以使用 git cherry-pick --abort
,恢復分支到 cherry-pick 之前的狀態。
git cherry-pick -x <commit_id>
增加 -x 引數,表示保留原提交的作者資訊進行提交。
在 Git 1.7.2 版本開始,新增了支援批量 cherry-pick ,就是可以一次將一個連續的時間序列內的 commit ,設定一個開始和結束的 commit ,進行 cherry-pick 操作。
git cherry-pick <start-commit-id>…<end-commit-id>
上述命令將從start-commit-id開始到end-commit-id之間的所有commit-id提交記錄都合併過來,需要注意的是,start-commit-id必須比end-commit-id提前提交。
cherry-pick與rebase的區別
cherry-pick 操作的是某一個或某幾個 commit,rebase 操作的是整個分支。
補丁
git apply xx.patch
需要自己重新 commit。xx.patch 必須從git diff
中獲得,才能使用 git apply
。
git am yy.patch
會保留commit資訊,yy.patch是從git format–patch
獲得的。
碼字不易,如果覺得對你有幫助,可以點個贊鼓勵一下!