一文搞定Git!
Git
通俗來講Git就是一個程式碼版本控制系統,多個開發人員可以協同開發,開發時可以將程式碼提交到本地,開發完成後,push到遠端即可,不用到處備份copy程式碼,方便檢視版本間的diff。
安裝git
快速上手
-
首先我們需要在終端介面初始化git資料夾,這裡我們建立了demo資料夾並初始化
$ mkdir demo && cd demo $ git init 已初始化空的 Git 倉庫於 /private/tmp/demo/.git/
在初始化後,本地目錄的檔案就是在工作區中,在執行add後就新增到了暫存區,commit之後就正式存在本地倉庫了
-
建立一個README.md檔案,並新增Git中
$ touch README.md $ echo '# git demo' > README.md $ cat README.md # git demo
-
新增到stage中
$ git add README.md
-
生成一個提交到本地倉庫, -m後跟的內容為本次提交的描述資訊,提交的檔案為已經add到stage中的檔案
$ git commit -m "add README.md" [master(根提交) 8c28b6f] add README.md 1 file changed, 1 insertion(+) create mode 100644 README.md
-
隨時檢視本地git狀態
$ git status 位於分支 master 無檔案要提交,乾淨的工作區
如圖就表示工作區中的檔案均已提交到本地git倉庫中
-
新增遠端倉庫(可以到Github中建立遠端倉庫,獲取地址),origin為遠端倉庫名,可以自行指定
git remote add origin git@github.com:icankeep/demo.git
可以通過下面命令檢視是否新增遠端倉庫成功
$ git remote show origin * 遠端 origin 獲取地址:git@github.com:icankeep/demo.git 推送地址:git@github.com:icankeep/demo.git HEAD 分支:(未知)
-
push本地提交到遠端倉庫
$ git push origin master 總共 0(差異 0),複用 0(差異 0),包複用 0 remote: remote: Create a pull request for 'master' on GitHub by visiting: remote: https://github.com/icankeep/demo/pull/new/master remote: To github.com:icankeep/demo.git * [new branch] master -> master
以上我們就完成了最簡單的git提交
進階
檢視分支
-
檢視本地分支
$ git branch * dev master merge_demo rebase_demo
-
檢視所有分支
$ git branch -a dev * master merge_demo rebase_demo remotes/origin/dev remotes/origin/master
建立並切換分支
一般來說,一個專案組的主分支為master,當我們開發時,會建立一個dev分支,在本地開發測試完成後會合併到線上的分支,如staging,提交到線上staging測試完成後,再合併到主分支釋出。我們可以使用下面的命令進行建立並切換分支
$ git checkout -b dev
切換到一個新分支 'dev'
git checkout
一般有以下幾種用途:
-
切換建立新分支
-
檢出commit,該操作會檢出該commit,並detach(和
git reset
不一樣,reset是在當前分支回退,checkout不影響當前分支,只是檢出)。如下,switch是新版本git引入切換分支的命令$ git checkout 2ce5a34 注意:正在切換到 '2ce5a34'。 您正處於分離頭指標狀態。您可以檢視、做試驗性的修改及提交,並且您可以在切換 回一個分支時,丟棄在此狀態下所做的提交而不對分支造成影響。 如果您想要通過建立分支來保留在此狀態下所做的提交,您可以通過在 switch 命令 中新增引數 -c 來實現(現在或稍後)。例如: git switch -c <新分支名> 或者撤銷此操作: git switch - 通過將配置變數 advice.detachedHead 設定為 false 來關閉此建議 HEAD 目前位於 2ce5a34 master demo
-
去除對暫存區中檔案的修改
git checkout -- filename
拉取遠端分支
-
git fetch
會將遠端commit更新到本地,但並不會主動合併$ git fetch origin master 來自 github.com:icankeep/demo * branch master -> FETCH_HEAD
-
git pull
就相當於git fetch origin master && git merge origin/master
將修改儲存進緩衝堆疊
如果暫存區的內容發生了改變,想要將這個改變暫時儲存,可以使用git stash
如下,我們修改了README.md,新增了test檔案
$ git status
位於分支 dev
要提交的變更:
(使用 "git restore --staged <檔案>..." 以取消暫存)
修改: README.md
尚未暫存以備提交的變更:
(使用 "git add <檔案>..." 更新要提交的內容)
(使用 "git restore <檔案>..." 丟棄工作區的改動)
修改: test
按照下面命令就可以儲存啦
$ git stash
儲存工作目錄和索引狀態 WIP on dev: ea15522 Merge branch 'merge_demo'
可以使用git stash list
和git stash show stash@{0}
檢視stash資訊
$ git stash list
stash@{0}: WIP on dev: ea15522 Merge branch 'merge_demo'
$ git stash show stash@{0}
README.md | 1 +
test | 1 +
2 files changed, 2 insertions(+)
將緩衝堆疊中內容提取出來
$ git stash pop
位於分支 dev
尚未暫存以備提交的變更:
(使用 "git add <檔案>..." 更新要提交的內容)
(使用 "git restore <檔案>..." 丟棄工作區的改動)
修改: README.md
修改: test
修改尚未加入提交(使用 "git add" 和/或 "git commit -a")
丟棄了 refs/stash@{0}(f6965744573d97e52b165e886d625ae1ddccf36a)
檢視提交歷史
當我們開發完程式碼git commit之後,我們就可以通過下面的命令檢視提交歷史
$ git log
commit abf83aa02ceb51e71d209777e2411b27a0f6b417
Author: passer <whzhoua@gmail.com>
Date: Sat Nov 7 21:32:32 2020 +0800
add README.md
如圖,每個commit都有對應的一個hash值(基本不可能碰撞)
檢視檔案修改差異
後續如果我們需要開發,可以通過git diff等檢視修改後的檔案和之前commit檔案的差異
$ git diff README.md
diff --git a/README.md b/README.md
index 7b81bad..b4f319c 100644
--- a/README.md
+++ b/README.md
@@ -4,3 +4,4 @@ master demo
1
2
3
+modify some things
合併分支
當程式碼在本地開發並測試完成後,我們一般需要將程式碼合併到其他正式分支,解決衝突的具體操作我們在後面rebase中說明
$ git checkout master
$ git merge dev
合併多個提交rebase
rebase是git中非常強大的功能,既可以merge分支,也可以合併修改commit資訊等。當我們本地開發時,可能會經常遇到剛提交完一個commit,發現程式碼中還有一些錯誤,於是又提交一個commit,會造成一個功能太多個commit,提交資訊混亂,於是我們就需要合併這些無用的commit。
-
git rebase 分支名
git rebase demo
指當前分支合併demo分支,git merge
和git rebase
的差異在於如果當前分支已經有了新的提交(demo分支中不存在的提交),git merge
就會產生一個merge commit(即一個額外的提交),git rebase
則不會。實踐出真知,直接開始操作在之前master分支"add README.md"提交之後切出新建立的rebase_demo分支和merge_demo分支
git checkout -b rebase_demo echo 'rebase demo' >> README.md git commit -am "rebase demo"
通過git log檢視提交歷史,發現已經提交
$ git log --graph --pretty=oneline --abbrev-commit * 0eec621 (HEAD -> rebase_demo) rebase demo * abf83aa (master) README.md
切換到master分支rebase我們的rebase_demo分支
$ git checkout master 切換到分支 'master'
$ git rebase rebase_demo 成功變基並更新 refs/heads/master。
$ git log --graph --pretty=oneline --abbrev-commit * 0eec621 (HEAD -> master, rebase_demo) rebase demo * abf83aa README.md
將rebase_demo分支合併到master分支成功,並且沒有產生新的提交,我們接著通過merge的方式來看有沒有新的提交
git checkout -b merge_demo echo 'merge demo' >> README.md git commit -am "merge demo"
通過
git log
檢視提交歷史,發現已經提交$ git log --graph --pretty=oneline --abbrev-commit * 65d472a (HEAD -> merge_demo) merge demo * abf83aa (master) README.md
git checkout master git merge merge_demo
$ git log --graph --pretty=oneline --abbrev-commit * 65d472a (HEAD -> master) merge demoREADME.md * abf83aa README.md
可知,當發起合併的分支中沒有新commit時,rebase和merge都是不會產生新的提交的,我們現在來看看當存在新提交時,會是什麼情況
首先,我們來看下當前的分支情況
$ git log --graph --pretty=oneline --abbrev-commit --all * 1fe102c (merge_demo) merge demo | * 0eec621 (rebase_demo) rebase demo |/ * abf83aa (HEAD -> master) README.md
master當前位於第一個提交,而rebase_demo分支提交了一個rebase demo, merge_demo提交了一個merge demo,為了產生衝突,我們在master分支提交一個master demo即可
echo 'master demo' >> README.md git commit -am "master demo"
$ git log --graph --pretty=oneline --abbrev-commit --all * 2ce5a34 (HEAD -> master) master demo | * 1fe102c (merge_demo) merge demo |/ | * 0eec621 (rebase_demo) rebase demo |/ * abf83aa README.md
此時每個分支都對檔案README.md做出了修改,這時將rebase_demo或merge_demo合併到master,都將產生衝突
$ git rebase rebase_demo 自動合併 README.md 衝突(內容):合併衝突於 README.md error: 不能應用 2ce5a34... master demo Resolve all conflicts manually, mark them as resolved with "git add/rm <conflicted_files>", then run "git rebase --continue". You can instead skip this commit: run "git rebase --skip". To abort and get back to the state before "git rebase", run "git rebase --abort". 不能應用 2ce5a34... master demo
通過git status檢視狀態
$ git status 互動式變基操作正在進行中;至 0eec621 最後一條命令已完成(1 條命令被執行): pick 2ce5a34 master demo 未剩下任何命令。 您在執行將分支 'master' 變基到 '0eec621' 的操作。 (解決衝突,然後執行 "git rebase --continue") (使用 "git rebase --skip" 跳過此補丁) (使用 "git rebase --abort" 以檢出原有分支) 未合併的路徑: (使用 "git restore --staged <檔案>..." 以取消暫存) (使用 "git add <檔案>..." 標記解決方案) 雙方修改: README.md 修改尚未加入提交(使用 "git add" 和/或 "git commit -a")
修改衝突檔案,將<<<<<<< HEAD >>>>>>> 2ce5a34… master demo之間的內容修改成最終的,wq儲存退出,重新
git add
$ vim README.md # git demo <<<<<<< HEAD rebase demo ======= # master master demo >>>>>>> 2ce5a34... master demo
$ git add README.md $ git rebase --continue
rebase_demo分支已經rebase到master分支,並沒有產生新的提交
$ git log --graph --pretty=oneline --abbrev-commit --all * 24e6dfa (HEAD -> master) master demo * 0eec621 (rebase_demo) rebase demo | * 1fe102c (merge_demo) merge demo |/ * abf83aa README.md
回到最初狀態繼續嘗試下merge
通過git reflog可以檢視所以git操作的id,隨時可以回退到對應的id
$ git reflog 24e6dfa (HEAD -> master) HEAD@{0}: rebase (continue) (finish): returning to refs/heads/master 24e6dfa (HEAD -> master) HEAD@{1}: rebase (continue): master demo 0eec621 (rebase_demo) HEAD@{2}: rebase (start): checkout rebase_demo 2ce5a34 HEAD@{3}: commit: master demo ...
我們通過git reset回到對應操作id上
$ git reset --hard 2ce5a34 HEAD 現在位於 2ce5a34 master demo
$ git log --graph --pretty=oneline --abbrev-commit --all * 2ce5a34 (HEAD -> master) master demo | * 1fe102c (merge_demo) merge demo |/ | * 0eec621 (rebase_demo) rebase demo |/ * abf83aa README.md
一切如初,繼續嘗試merge
$ git merge merge_demo 自動合併 README.md 衝突(內容):合併衝突於 README.md 自動合併失敗,修正衝突然後提交修正的結果。
$ git status 位於分支 master 您有尚未合併的路徑。 (解決衝突並執行 "git commit") (使用 "git merge --abort" 終止合併) 未合併的路徑: (使用 "git add <檔案>..." 標記解決方案) 雙方修改: README.md 修改尚未加入提交(使用 "git add" 和/或 "git commit -a")
vim README.md # git demo <<<<<<< HEAD # master master demo ======= merge demo >>>>>>> merge_demo
發現解決完衝突之後,會提示需要commit來結束衝突,所以當存在衝突時merge會產生額外一個commit
git add README.md $ git status 位於分支 master 所有衝突已解決但您仍處於合併中。 (使用 "git commit" 結束合併)
$ git commit -m "merge" [master 52ecde5] merge
$ git log --graph --pretty=oneline --abbrev-commit --all * 52ecde5 (HEAD -> master) merge |\ | * 1fe102c (merge_demo) merge demo * | 2ce5a34 master demo |/ | * 0eec621 (rebase_demo) rebase demo |/ * abf83aa README.md
可知產生了52ecde5這個額外的commit,以上就是rebase和merge合併分支上的區別
-
git rebase
合併commit檢視當前master分支狀態
$ git log --graph --pretty=oneline --abbrev-commit * d576335 (HEAD -> master) 開發測試3 * b30a41e 開發測試2 * 209a0c1 開發測試 * 2ce5a34 master demo * abf83aa README.md
可知,存在一些開發測試過程中的commit,我們需要對其進行合併,即將3個開發測試的commit合併成一個,可以執行如下命令,3為合併的commit數目
git rebase -i HEAD~3
就會進入如下介面
pick 209a0c1 開發測試 pick b30a41e 開發測試2 pick d576335 開發測試3 # 變基 2ce5a34..d576335 到 2ce5a34(3 個提交) # # 命令: # p, pick <提交> = 使用提交 # r, reword <提交> = 使用提交,但修改提交說明 # e, edit <提交> = 使用提交,進入 shell 以便進行提交修補 # s, squash <提交> = 使用提交,但融合到前一個提交 # f, fixup <提交> = 類似於 "squash",但丟棄提交說明日誌 # x, exec <命令> = 使用 shell 執行命令(此行剩餘部分) # b, break = 在此處停止(使用 'git rebase --continue' 繼續變基) # d, drop <提交> = 刪除提交 # l, label <label> = 為當前 HEAD 打上標記 # t, reset <label> = 重置 HEAD 到該標記 # m, merge [-C <commit> | -c <commit>] <label> [# <oneline>] # . 建立一個合併提交,並使用原始的合併提交說明(如果沒有指定 # . 原始提交,使用註釋部分的 oneline 作為提交說明)。使用 # . -c <提交> 可以編輯提交說明。 # # 可以對這些行重新排序,將從上至下執行。 # # 如果您在這裡刪除一行,對應的提交將會丟失。 # # 然而,如果您刪除全部內容,變基操作將會終止。
按照提示修改pick為f,儲存並退出即可
pick 209a0c1 開發測試 f b30a41e 開發測試2 f d576335 開發測試3
發現commit已經合併了
$ git log --graph --pretty=oneline --abbrev-commit * 86b2868 (HEAD -> master) 開發測試 * 2ce5a34 master demo * abf83aa README.md
當rebase用於合併commit時
如果需要修改commit資訊,可以使用如下命令
git commit --amend
進入如下介面,修改並儲存即可
開發測試 # 請為您的變更輸入提交說明。以 '#' 開始的行將被忽略,而一個空的提交 # 說明將會終止提交。 # # 日期: Sat Nov 7 23:20:29 2020 +0800 # # 位於分支 master # 要提交的變更: # 修改: README.md #
發現commit資訊已經被修正
$ git log --graph --pretty=oneline --abbrev-commit * 5d0d00a (HEAD -> master) 正式提交 * 2ce5a34 master demo * abf83aa README.md
重置提交reset
簡單粗暴,直接命令上手,下面命令將commitId改成要回退到的commit hash值在執行就可以回退到指定的commit
git reset --hard commitId
除了–hard還有–mixed和–soft, git reset預設是–mixed
-
mixed
$ git reset --mixed 2ce5a34 重置後取消暫存的變更: M README.md
使用git status檢視狀態,發現之前commit的檔案已經回退到工作區
$ git status 位於分支 master 尚未暫存以備提交的變更: (使用 "git add <檔案>..." 更新要提交的內容) (使用 "git restore <檔案>..." 丟棄工作區的改動) 修改: README.md 修改尚未加入提交(使用 "git add" 和/或 "git commit -a")
-
soft
$ git reset --soft 2ce5a34 $ git status 位於分支 master 要提交的變更: (使用 "git restore --staged <檔案>..." 以取消暫存) 修改: README.md
發現使用soft重置之後,修改內容會新增到暫存區
-
hard
$ git reset --hard 2ce5a34 HEAD 現在位於 2ce5a34 master demo
$ git status 位於分支 master 無檔案要提交,乾淨的工作區
使用hard重置提交,提交的內容均會消失,如果不小心重置了,可以用git reflog檢視並重置到指定的操作上哦!
提取commit
我們在一個分支中可能會需要另一個分支的一個commit,這個時候我們就可以用到下面這個命令進行提取
如下狀態,我們如果在rebase_demo分支獲取master分支5d0d00a這個commit的內容,我們就可以使用cherry-pick
$ git log --graph --pretty=oneline --abbrev-commit --all
* 5d0d00a (HEAD -> master) 正式提交
* 2ce5a34 master demo
| * 1fe102c (merge_demo) merge demo
|/
| * 0eec621 (rebase_demo) rebase demo
|/
* abf83aa README.md
git cherry-pick 5d0d00a
給commit打上標籤
給當前分支最新的提交打上標籤
$ git tag v1.0
檢視標籤
$ git tag
v1.0
$ git log --graph --pretty=oneline --abbrev-commit
* ea15522 (HEAD -> dev, tag: v1.0, master) Merge branch 'merge_demo'
將標籤推送到遠端倉庫
$ git push origin v1.0
總共 0(差異 0),複用 0(差異 0),包複用 0
To github.com:icankeep/demo.git
* [new tag] v1.0 -> v1.0
推送本地的所有tag
git push origin --tags
將標籤打到具體的commit上
$ git tag v0.7 8c28b6f
可以看到v0.7已經打到8c28b6f上了
$ git show v0.7
commit 8c28b6fbe67d37723f43f1df20a0d360cabf14f5 (tag: v0.7)
Author: passer <whzhoua@gmail.com>
Date: Sun Nov 8 13:51:04 2020 +0800
add README.md
如果打錯標籤了,需要刪除,可以按照下面的命令
$ git tag -d v0.7
已刪除標籤 'v0.7'(曾為 8c28b6f)
當然,這只是在本地刪除標籤,如果該標籤已經推送到遠端,想要刪除的話,還得加上下面這一步
$ git push origin :refs/tags/v0.7
To github.com:icankeep/demo.git
- [deleted] v0.7
相關文章
- 一文搞定規範化Git CommitGitMIT
- 一文搞定 Spring Data JPASpring
- 一文替你全部搞定:MySQL命令。MySql
- 一文搞定防盜鏈設計
- 一文搞定!在 OpenStack 上部署 HadoopHadoop
- 一文搞定資訊打點——超詳細
- 一文快速掌握 Git 用法Git
- 機器學習新手必看:一文搞定SVM演算法機器學習演算法
- 一文搞定二叉排序(搜尋)樹排序
- 面試中Java泛型問題一文搞定面試Java泛型
- 一文輕鬆搞定 tarjan 演算法(二)演算法
- 【RabbitMQ】一文帶你搞定RabbitMQ延遲佇列MQ佇列
- 一文搞定HashMap的實現原理和麵試HashMap
- 一文搞定Jackson解析JSON資料JSON
- unittest系統(八)一文搞定unittest重試功能
- 一文讀懂git核心工作原理Git
- 一文搞定Samba雲伺服器配置(阿里雲)Samba伺服器阿里
- 一文輕鬆搞定批處理框架 Spring Batch框架SpringBAT
- 一文搞定POI,再也不怕excel匯入匯出了Excel
- 一文徹底搞定Redis與MySQL的資料同步RedisMySql
- 一文入門Kafka,必知必會的概念通通搞定Kafka
- 【專案實踐】一文帶你搞定Spring Security + JWTSpringJWT
- 一文搞定FastDFS分散式檔案系統配置與部署AST分散式
- 一文搞定 Windows Terminal 設定與 zsh 安裝 (非WSL)Windows
- 一文搞定全場景K3s離線安裝
- 一文搞定K8S監控告警平臺選型K8S
- 一文讓你明白 Git 分支是如何工作的Git
- 一文搞定:前端如何選擇Angular、React和Vue三大主流框架前端AngularReactVue框架
- 實用且簡單的Git教程,輕鬆搞定多人開發Git
- 專案實戰之跨域處理~一文搞定所有跨域需求跨域
- 備戰雙十一 | 電商廣告主高效投放指南,曝光起量一文搞定!
- 一文徹底搞定Spring Security 認證,實現登陸登出功能Spring
- Idea+Git+GitHub圖文教程,一篇教程幫你搞定IdeaGithub
- 一文讀懂 Git fetch 和 Git pull 的終極區別(帶實驗結果)Git
- 一文搞定Python大小寫轉換,首字母大寫,去除特殊字元Python字元
- 一文看懂遷移學習:怎樣用預訓練模型搞定深度學習?遷移學習模型深度學習
- 一文搞定 KubeKey 3.1.1 離線部署 KubeSphere 3.4.1 和 Kubernetes v1.28
- 一文搞定陣列扁平化(超全面的陣列拉平方案及實現)陣列