柚子快報(bào)邀請(qǐng)碼778899分享:java git常用操作
柚子快報(bào)邀請(qǐng)碼778899分享:java git常用操作
一、git 工作流程
git 有四個(gè)區(qū)域:
3個(gè)本地區(qū)域
工作區(qū)(Workspace): 存放項(xiàng)目代碼的地方。暫存區(qū)(Stage): 存放臨時(shí)的改動(dòng), 事實(shí)上它只是一個(gè)文件, 保存即將提交的文件列表信息。資源庫(kù)(Repository): 安全存放數(shù)據(jù)的位置, 這里面有提交到所有版本的數(shù)據(jù)。其中 HEAD 指向最新放入倉(cāng)庫(kù)的版本。 1個(gè)遠(yuǎn)程區(qū)域
遠(yuǎn)程庫(kù)(Remote): 托管代碼的服務(wù)器。
二、git 初始化
$ mkdir git-study && cd git-study
$ git init
$ ls -la
total 0
drwxr-xr-x 3 kino staff 96 11 23 17:18 .
drwxr-xr-x 16 kino staff 512 11 23 17:18 ..
drwxr-xr-x 9 kino staff 288 11 23 17:18 .git
創(chuàng)建成功之后, 會(huì)出現(xiàn)一個(gè) .git 的隱藏文件夾, 這個(gè)就是這個(gè)項(xiàng)目的 git 倉(cāng)庫(kù), 以后所有的 git 操作歷史提交記錄信息全都在此, 只要這個(gè)文件夾還存在, 就可以記住我們所有的 git 操作。
三、git 配置相關(guān)常用命令
3.1 git config
查看 git 配置
$ git config --list
credential.helper=osxkeychain
user.name=kino
user.email=kino@gmail.com
core.autocrlf=input
core.quotepath=false
core.repositoryformatversion=0
core.filemode=true
core.bare=false
core.logallrefupdates=true
core.ignorecase=true
core.precomposeunicode=true
修改 git 配置文件
$ git config -e # 針對(duì)當(dāng)前倉(cāng)庫(kù)
$ git config -e --global # 針對(duì)系統(tǒng)上的所有倉(cāng)庫(kù)
設(shè)置提交代碼時(shí)的用戶信息
$ git config --global user.name "yourUserName" # 去掉 --global 就只對(duì)當(dāng)前倉(cāng)庫(kù)生效
$ git config --gloabl user.email "yourEmail" # 去掉 --global 就只對(duì)當(dāng)前倉(cāng)庫(kù)生效
四、git 日常操作
git add: 將文件添加到暫存區(qū)
git status: 查看在你上次提交之后是否有對(duì)文件進(jìn)行再次修改
git diff: 比較文件在暫存區(qū)和工作區(qū)的差異
git ls-files: 查看暫存區(qū)的文件
git cat-file -p: 查看暫存區(qū)文件中的內(nèi)容
git commit: 提交暫存區(qū)文件到本地倉(cāng)庫(kù)
git rm: 刪除文件
4.1 提交代碼
4.1.1 git add
語(yǔ)法:
# 1. 該命令可以將文件添加到暫存區(qū)
$ git add [file1] [file2] ...
# 2. 添加指定目錄到暫存區(qū)
$ git add [dir]
# 3. 添加當(dāng)前目錄下所有文件進(jìn)入暫存區(qū)
$ git add .
示例:
$ touch 1.txt 2.txt 3.txt 4.txt
$ ll
total 8
-rw-r--r-- 1 kino staff 0 7 5 18:30 1.txt
-rw-r--r-- 1 kino staff 0 7 5 18:30 2.txt
-rw-r--r-- 1 kino staff 0 7 5 18:31 3.txt
-rw-r--r-- 1 kino staff 0 7 5 18:31 4.txt
-rw-r--r-- 1 kino staff 13 7 5 18:30 README.md
# 添加 1.txt 和 2.txt 進(jìn)入暫存區(qū)
$ git add 1.txt 2.txt
4.1.2 git status
查看在你上次提交之后是否有對(duì)文件進(jìn)行再次修改。
$ git status
On branch main
Your branch is up to date with 'origin/main'.
Changes to be committed:
(use "git restore --staged
new file: 1.txt
new file: 2.txt
Untracked files:
(use "git add
3.txt
4.txt
$ git status -s
A 1.txt
A 2.txt
?? 3.txt
?? 4.txt
$ git commit -m "提交"
[main 26c1139] 提交
2 files changed, 0 insertions(+), 0 deletions(-)
create mode 100644 1.txt
create mode 100644 2.txt
$ echo 11111 >> 1.txt
$ echo 33333 >> 3.txt
$ git add 3.txt
$ git status -s
M 1.txt
AM 3.txt
?? 4.txt
A 表示新提交M 表示提交過(guò),并且本地又修改了AM 表示有改動(dòng)
4.1.3 git diff
比較文件的不同, 即比較文件在暫存區(qū)和工作區(qū)的差異
git diff 顯示已經(jīng)寫入暫存區(qū)和已經(jīng)被修改但尚未寫入暫存區(qū)文件的區(qū)別
應(yīng)用場(chǎng)景:
尚未緩存的改動(dòng): git diff查看已經(jīng)緩存的改動(dòng): git diff --cached查看緩存成功和未緩存的所有改動(dòng): git diff HEAD顯示摘要而非整個(gè)diff: git diff --stat
刪除原來(lái)的項(xiàng)目重新clone
$ rm -rf git-study
$ git init
$ cd git-study
$ echo 1111 >> README.md
$ git add . && git commit -m "readme"
$ echo 2222 >> README.md
# 查看暫未添加至緩存區(qū)的改動(dòng)
$ git diff
diff --git a/README.md b/README.md
index 5f2f16b..4f142ee 100644
--- a/README.md
+++ b/README.md
@@ -1 +1,2 @@
1111
+2222
# 顯示簡(jiǎn)略信息
$ git diff --stat
README.md | 1 +
1 file changed, 1 insertion(+)
# 查看已經(jīng)添加至緩存區(qū)的改動(dòng)
$ git add README.md
$ git diff --cached
diff --git a/README.md b/README.md
index 5f2f16b..4f142ee 100644
--- a/README.md
+++ b/README.md
@@ -1 +1,2 @@
1111
+2222
# 查看不在緩存區(qū) & 在緩存區(qū)的改動(dòng)
$ git diff HEAD
diff --git a/README.md b/README.md
index 5f2f16b..4f142ee 100644
--- a/README.md
+++ b/README.md
@@ -1 +1,2 @@
1111
+2222
4.1.4 git ls-files
查看暫存區(qū)的文件
$ git ls-files
README.md
可選參數(shù):
-c: 默認(rèn)-d: 顯示刪除的文件-m: 顯示被修改過(guò)的文件-o: 顯示沒有被 git 跟蹤過(guò)的文件-s: 顯示 mode 以及對(duì)應(yīng)的 Blog對(duì)象, 進(jìn)而可以獲取暫存區(qū)中對(duì)應(yīng)文件的內(nèi)容
4.1.5 git cat-file -p
查看暫存區(qū)文件中的內(nèi)容
$ git ls-files -s
100644 5cf7833392d65968a05971b9923f36a1ec46d7f7 0 README.md
$ git cat-file -p 5cf7
1111
2222
4.1.6 git commit
提交暫存區(qū)文件到本地倉(cāng)庫(kù)
$ git commit -m [message]
提交暫存區(qū)的指定文件到本地倉(cāng)庫(kù)
$ git commit [file1] [file2] ... -m [message]
4.1.7 git rm
git rm 用于刪除文件
1、將文件從暫存區(qū)和工作區(qū)中刪除
$ git rm 1.txt 2.txt
2、將文件從暫存區(qū)和工作區(qū)中強(qiáng)制刪除
# 可以加上 -f, 表示強(qiáng)制刪除之前修改過(guò)而且 add 到暫存區(qū)的文件
$ git rm -f 1.txt 2.txt
3、將文件從暫存區(qū)刪除,在工作區(qū)保留
git rm --cached 1.txt 2.txt
4.2 分支操作
# 查看分支
$ git branch -a
# 基于當(dāng)前分支創(chuàng)建一個(gè)新分支
$ git checkout -b feature/hotfix-001
# 基于指定分支創(chuàng)建一個(gè)新的分支
$ git checkout -b feature/hotfix-002 master
# 切換分支
$ git checkout master
# 刪除分支
$ git branch -d feature/hotfix-001
4.3 更新操作
@TODO
4.4 合并沖突
簡(jiǎn)單制造一個(gè)沖突
# 再遷出一個(gè)分支(模擬其他人的修改操作)
$ git checkout -b feature/hotfix-001 feature/hotfix-002
# 修改文件
$ echo 3333 >> README.md
$ git add README.md
$ git commit -m "hotfix-001: add newline"
# 合并到master
$ git checkout master
$ git merge feature/hotfix-001
$ git checkout feature/hotfix-002
$ vim README.md
# 在第三行添加
3344
$ git add README.md
$ git commit -m "hotfix-002: add newline"
$ git checkout master
# 再合并代碼就會(huì)出現(xiàn)沖突提示
# 這個(gè)時(shí)候不可以進(jìn)行任何分支切換和commit操作,需要按照提示將沖突解決。
$ git merge feature/hotfix-002
Auto-merging README.md
CONFLICT (content): Merge conflict in README.md
Automatic merge failed; fix conflicts and then commit the result.
查看沖突文件內(nèi)容
$ vim README.md
1111
2222
<<<<<<< HEAD
3333
=======
3344
>>>>>>> feature/hotfix-002
從 <<<<<<< HEAD 開始, 到 ======= 都是主分支已經(jīng)存在的內(nèi)容。從 ======= 開始, 到 >>>>>>> feature/hotfix-002 都是 merge 過(guò)來(lái)的分支的內(nèi)容。
解決沖突,視情況保留(刪除)記錄
$ vim README.md
1111
2222
3333
3344
# 沖突解決完成之后, 再次提交代碼
$ git commit -a
# 查看變更記錄
commit 8715c66d8ca756077040ce6d783c6caf470d115e (HEAD -> master)
Merge: b89c0c5 ba903ae
Author: kino
Date: Wed Nov 23 18:29:17 2022 +0800
Merge branch 'feature/hotfix-002'
commit ba903aebecb447d6f485108f0321b15f6c009886 (feature/hotfix-002)
Author: kino
Date: Wed Nov 23 18:19:54 2022 +0800
hotfix-002: add newline
commit b89c0c592ba11894acb2cd93564c5e43934065fb (feature/hotfix-001)
Author: kino
Date: Wed Nov 23 18:16:23 2022 +0800
hotfix-001: add newline
4.3 暫存代碼保護(hù)現(xiàn)場(chǎng)
項(xiàng)目經(jīng)理提了一個(gè)新的需求, 開發(fā)就需要從 master 分支遷出一個(gè)新的分支進(jìn)行功能開發(fā)(例如遷出新分支為dev), 如果在開發(fā)過(guò)程工, 生產(chǎn)上有緊急 bug 需要修復(fù), 就可以用到 git stash 了。
git stash 可以將現(xiàn)在的 工作區(qū)全部的修改、新增、刪除等操作,全部保存起來(lái)。
git stash 的常用命令:
git stash save 'save message': 執(zhí)行存儲(chǔ)時(shí), 添加備注, 方便查找, 當(dāng)然只執(zhí)行 git stash 也是可以的, 但查找時(shí)不方便。git stash list: 查看 stash 了哪些存儲(chǔ)。git stash show: 顯示做了哪些改動(dòng), 默認(rèn) show 第一個(gè)存儲(chǔ), 如果要顯示其他的存儲(chǔ), 后面加 stash@{$num}, 比如第二個(gè): git stash show stash@{1}git stast show -p: 顯示第一個(gè)存儲(chǔ)的改動(dòng), 如果想顯示其他存儲(chǔ), 則: git stash show stash@{$num} -p, 比如第二個(gè): git stash show stash@{1} -pgit stash apply: 應(yīng)用某個(gè)存儲(chǔ), 但不會(huì)把存儲(chǔ)從存儲(chǔ)列表中刪除, 默認(rèn)使用第一個(gè)存儲(chǔ), 即 stash@{0}, 如果要是用其他, 則: git stash apply stash@{$num}, 比如第二個(gè): git stash apply stash@{1}git stash pop: 恢復(fù)之前緩存的工作目錄, 將緩存列表中對(duì)應(yīng)的 stash 刪除, 并將對(duì)應(yīng)修改應(yīng)用到當(dāng)前的工作目錄下, 默認(rèn)為第一個(gè) stash, 即 stash@{0}, 如果要應(yīng)用并刪除其他 stash, 則: git stash pop stash@{$num}, 比如應(yīng)用并刪除第二個(gè): git stash pop stash@{1}git stash drop stash@{num}: 丟棄 stash@{num} 存儲(chǔ), 從列表中刪除這個(gè)存儲(chǔ)git stash clear: 刪除所有緩存的 stash
開始模擬現(xiàn)場(chǎng)
# git 初始化
$ cd .. && rm -rf git-study && mkdir git-study && cd git-study && git init
$ echo 'file1 init' > file1.txt
$ echo 'file2 init' > file2.txt
$ git add .
$ git commit -m 'change: add file1 & file2'
[master (root-commit) 525c358] change: add file1 & file2
2 files changed, 2 insertions(+)
create mode 100644 file1.txt
create mode 100644 file2.txt
# 然后從 master 分支創(chuàng)建兩個(gè)新的 feature 分支
$ git branch feature1
$ git branch feature2
# checkout feature1, 修改 file1.txt, 并在 feature1 上創(chuàng)建兩次提交
$ git checkout feature1
$ echo 'add file1.txt code 1' >> file1.txt
$ git add file1.txt
$ git commit -m 'change file1 no.1'
$ echo 'add file2.txt code 2' >> file1.txt
$ git add file1.txt
$ git commit -m 'change file1 no.2'
# 目前 feature1 上的改動(dòng)內(nèi)容
$ cat file1.txt
file1 init
add file1.txt code 1
add file2.txt code 2
$ cat file2.txt
file2 init
# checkout feature2, 修改 file2.tx
$ git checkout feature2
$ echo 'add file2.txt code 1' >> file2.txt
$ git add file2.txt
$ git commit -m 'change file2 no.1'
# 目前 feature2 上的改動(dòng)內(nèi)容
$ cat file1.txt
file1 init
$ cat file2.txt
file2 init
add file2.txt code 1
# 假設(shè)不小心將 feature2 合并到了 feature1, 并在 feature1 繼續(xù)進(jìn)行了代碼開發(fā)并提交
$ git checkout feature1
$ git merge feature2
$ echo 'add file1.txt no.3 & code end' >> file1.txt
$ git add file1.txt
$ git commit -m 'change file1 no.3'
# 此時(shí) feature1 上所有文件的內(nèi)容
$ cat file1.txt
file1 init
add file1.txt code 1
add file2.txt code 2
add file1.txt no.3 & code end
$ cat file2.txt
file2 init
add file2.txt code 1
# 此時(shí)我們發(fā)現(xiàn)了不小心 merge 進(jìn)來(lái)的 feature2, 而且在這基礎(chǔ)上我們還有新的 commit, 如果我們想將 merge 剔除, 可以做如下操作
# 先查看需要還原 commit 的版本號(hào)
$ git log --oneline
8a1454f (HEAD -> feature1) change file1 no.3
422a454 Merge branch 'feature2' into feature1
4978e2c (feature2) change file2 no.1
ee4a50e change file1 no.2
dc397c1 change file1 no.1
525c358 (master) change: add file1 & file2
# 其中, 422a454 就是誤合并的 commitid
# 目前我們需要做的就是撤銷已提交的 commit, 回滾到 feature2 誤合并到 feature1 分支的 commit 版本。
$ git reset --mixed 422a454
Unstaged changes after reset:
M file1.txt
$ git log --oneline
422a454 (HEAD -> feature1) Merge branch 'feature2' into feature1
4978e2c (feature2) change file2 no.1
ee4a50e change file1 no.2
dc397c1 change file1 no.1
525c358 (master) change: add file1 & file2
$ git diff file1.txt
diff --git a/file1.txt b/file1.txt
index 4a1ca46..6954af7 100644
--- a/file1.txt
+++ b/file1.txt
@@ -1,3 +1,4 @@
file1 init
add file1.txt code 1
add file2.txt code 2
+add file1.txt no.3 & code end ## 可以看見, feature1 最后一次提交已經(jīng)是未暫存狀態(tài)了
# 此時(shí), 我們就可以使用 git stash, 將撤銷的代碼存儲(chǔ)起來(lái),
$ git stash save 'save file1.txt reset code'
Saved working directory and index state On feature1: save file1.txt reset code
# 查看 stash 列表
$ git stash list
stash@{0}: On feature1: save file1.txt reset code
# 查看 status, 可以看見在工作空間已經(jīng)沒有了
$ git status
On branch feature1
nothing to commit, working tree clean
# 然后再撤銷 merge 相關(guān)的信息
$ git reset --hard HEAD~
# 再查看此時(shí)本地的文件內(nèi)容
$ cat file1.txt
file1 init
add file1.txt code 1
add file2.txt code 2
$ cat file2.txt
file2 init
# 接下來(lái)恢復(fù) feature1 上被撤銷的代碼
$ git stash list
stash@{0}: On feature1: save file1.txt reset code
$ git stash apply stash{0}
On branch feature1
Changes not staged for commit:
(use "git add
(use "git restore
modified: file1.txt
no changes added to commit (use "git add" and/or "git commit -a")
# 此時(shí)代碼就恢復(fù)回來(lái)了
$ cat file1.txt
file1 init
add file1.txt code 1
add file2.txt code 2
add file1.txt no.3 & code end
說(shuō)明: git stash會(huì)貯存及不會(huì)貯存的文件范圍
會(huì)貯存:
添加到暫存區(qū)的修改(staged changes)git跟蹤的但并未添加到暫存區(qū)的修改(unstaged changes) 不會(huì)貯存:
在工作目錄中新的文件(untracked files)被忽略的文件(ignored files)
當(dāng)然, 如果僅僅需要 刪除某個(gè) commit, 其實(shí)有更好的方法
# 假設(shè), 當(dāng)前已經(jīng)到了 git commit -m 'change file1 no.3', 當(dāng)前 log
$ git log
commit 3e6be928866581f1779bb0f0e84d29d068d698e8 (HEAD -> feature1)
Author: kino
Date: Thu Nov 24 23:30:31 2022 +0800
change file1 no.3
commit ef733ffec4e80ed851f353f2d8b2dba46b831bb6
Merge: 5e96765 7d9cebd
Author: kino
Date: Thu Nov 24 23:30:29 2022 +0800
Merge branch 'feature2' into feature1
...
# 我們可以直接 git revert 指定的 commit, 例如 上面 merge 的 commit id 是 ef733ffec4e80ed851f353f2d8b2dba46b831bb6
$ git revert -i ef733ffec4e80ed851f353f2d8b2dba46b831bb6 -m 1
# 注意, 已經(jīng)要加上 -m 1, 否則會(huì)報(bào)如下錯(cuò):
# error: commit ef733ffec4e80ed851f353f2d8b2dba46b831bb6 is a merge but no -m option was given.
# fatal: revert failed
# 在這里解釋下 -m 1 的含義:
# 從上面的 git log 可以看見 "Merge: 5e96765 7d9cebd" 的信息, 這代表著, 本次 merge 是使用當(dāng)前分支的 5e96765(commit) 和 feature2 分支的 7d9cebd(commit) 合并而來(lái), 我們可以做一下驗(yàn)證:
# # 首先 cat-file 5e96765
# $ git cat-file -p 5e96765
# tree fa6ff2fd55be9834b45f0be9d347b1670594ed17
# parent d27c172b6e876938eb39094801ca5e436a30b3c3
# author kino
# committer kino
# change file1 no.2
# # 然后取 tree 的 id 繼續(xù)查看, 可以看到, 這個(gè) tree 記錄該 commit 的兩個(gè)文件
# $ git cat-file -p fa6ff2fd55be9834b45f0be9d347b1670594ed17
# 100644 blob 4a1ca461271ec4e0041822373470703dca5d0626 file1.txt
# 100644 blob 18ffc0add953f06f00be32437b9f79e09af27d32 file2.txt
# # 然后取 file2.txt 的 id 繼續(xù)查看, 可以看到, 這個(gè) tree 記錄 該 file2.txt 的內(nèi)容為: file2 init
# $ git cat-file -p 18ffc0add953f06f00be32437b9f79e09af27d32
# file2 init
# # 然后我們?cè)?cat-file 7d9cebd
# tree 1b5c42acd113046ec223223affe7b3ef579a293b
# parent 9acd7882175075c0f3e2f44dfa0d91f3d0a673d1
# author kino
# committer kino
# change file2 no.1
# # 然后取 tree 的 id 繼續(xù)查看, 可以看到, 這個(gè) tree 記錄該 commit 的兩個(gè)文件
# git cat-file -p 1b5c42acd113046ec223223affe7b3ef579a293b
# 100644 blob 0c481f7fe4602d041634c353e31846bf1b638c37 file1.txt
# 100644 blob c6b0b29e598db81ef8e54ec955df78cfac4ae316 file2.txt
# # 然后取 file2.txt 的 id 繼續(xù)查看, 可以看到, 這個(gè) tree 記錄 該 file2.txt 的內(nèi)容
# git cat-file -p c6b0b29e598db81ef8e54ec955df78cfac4ae316
# file2 init
# add file2.txt code 1
# 由此我們可以得出結(jié)論, 5e96765 就是 feature1 在 Merge 之前的狀態(tài), 而 7d9cebd 就是 feature2 在 Merge 之前的狀態(tài)。
# 因?yàn)?一個(gè) Merge 記錄了兩個(gè)分支的 commit 信息, 所以, 在 revert merge 的時(shí)候,需要明確的支出, 要revert 到哪個(gè)commit, 因?yàn)槲覀兪窍肴∠?feature2 里面的內(nèi)容, 所以就是 -m 1
# ok, 回到正題, git revert 之后, 我們?cè)俨榭?log
$ git log --oneline
b4dde93 (HEAD -> feature1) Revert "Merge branch 'feature2' into feature1"
3e6be92 change file1 no.3
ef733ff Merge branch 'feature2' into feature1
5e96765 change file1 no.2
7d9cebd (feature2) change file2 no.1
d27c172 change file1 no.1
9acd788 (master) change: add file1 & file2
# 然后查看 file2.txt
$ cat file2.txt
file2 init
五、git 高級(jí)操作
5.1 git 撤銷操作
disk
commanddescription查看修改git diff查看狀態(tài)git status -> Changes not staged for comit撤銷文件修改git checkout
暫存區(qū)
commanddescription查看狀態(tài)git status -> Changes to be committed(綠色)從暫存區(qū)移除,但保留硬盤上的修改git reset
local
commanddescription撤銷commit(保留磁盤上的修改和暫存區(qū)記錄)git reset --soft HEAD~1撤銷commit(清除暫存區(qū)記錄, 只保留磁盤上的修改)git reset HEAD~1 == git reset --mixed HEAS~1撤銷commit(清除暫存區(qū)記錄, 清除磁盤上的修改)git reset --hard HEAD~1生成新的commitId,將上一個(gè)commit+的內(nèi)容變成commit-git revert HEAD提交遠(yuǎn)端gitgit push
git reset & git revert:
git reset: 只能回到之前某一個(gè)commit的狀態(tài)。git revert:撤銷中間任意一個(gè)commit。git revert 70a0;(git revert HEAD~1)
如果操作項(xiàng)目的分支是公共分支,只能通過(guò) git revert 生成一個(gè)新的 commitId,從這個(gè)結(jié)果上撤銷我們之前的修改。
git revert HEADgit push
如果操作項(xiàng)目的分支是個(gè)人分支,可以通過(guò)git reset撤銷我們之前的修改
git reset --hard HEAD~1git push -f
5.2 git 找回丟失文件(commit了)
恢復(fù)因?yàn)閳?zhí)行 git reset --hard COMMITID 丟失的文件
# 重新創(chuàng)建一個(gè)項(xiàng)目
$ cd .. && rm -rf git-study && mkdir git-study && cd git-study && git init
$ echo 'master message 1' >> master_1.txt
$ git add master_1.txt
$ git commit -m 'first commit'
$ echo 'master message 2' >> master_2.txt
$ git add master_2.txt
$ git commit -m 'No.2 commit'
# 在這兩次commit的基礎(chǔ)上, reset 到第一次(first commit)上
$ git log # 獲取第一次commitid
$ git reset --hard 4a9bcb880db85a1ca77807dea9b3adce29dc4fda
# 再次查看 log 信息, 此時(shí)可以看見只有一次commit了, 第二次 commit(No.2 commit) 已經(jīng)丟失
$ git log -n 2
git 提供了 git reflog 用來(lái)記錄你的每一次改變目錄樹的命令,使用好他就可以很方便的恢復(fù)你的提交:
4a9bcb8 (HEAD -> master) HEAD@{0}: reset: moving to 4a9bcb880db85a1ca77807dea9b3adce29dc4fda
80258ce HEAD@{1}: commit: No.2 commit
4a9bcb8 (HEAD -> master) HEAD@{2}: commit (initial): first commit
可以看到最上面一條記錄是將 HEAD 重新指向第一次的commit了, 同時(shí)也有顯示第二次 commit 的 commitid, 有了這個(gè) commitid, 就可以回滾了。
$ git reset --hard 80258ce
HEAD is now at 80258ce No.2 commit
$ git log
commit 80258ce0146f373d15a1991d61af4061687782bc (HEAD -> master)
Author: kino
Date: Thu Nov 24 02:26:10 2022 +0800
No.2 commit
commit 4a9bcb880db85a1ca77807dea9b3adce29dc4fda
Author: kino
Date: Thu Nov 24 02:25:06 2022 +0800
first commit
可以看到, commit 已被找回.
但是通常情況下, 可能會(huì)出現(xiàn)在 git reset 之后, 還有新的 commit, 如果直接 reset 恢復(fù)的 commit, 肯定會(huì)造成新的 commit 又丟失, 所以如果我們只是想恢復(fù)這個(gè)一個(gè) commit, 可以使用 git cherry-pick commitid 來(lái)單獨(dú)將這個(gè) commitid 恢復(fù)到當(dāng)前分支或者用 git merge 來(lái)做合并
$ git cherry-pick 04b0396
[master fbf401a] No.2 commit
Date: Thu Nov 24 02:38:14 2022 +0800
1 file changed, 1 insertion(+)
create mode 100644 master_2.txt
$ git log
commit fbf401a96bd9831c18ed02e9ee852cef8111ccb1 (HEAD -> master)
Author: kino
Date: Thu Nov 24 02:38:14 2022 +0800
No.2 commit
commit 1b5bfdb36ad01fb86d94b76654347f5de5475f37
Author: kino
Date: Thu Nov 24 02:38:05 2022 +0800
first commit
5.3 git 找回丟失文件(未commit,但添加暫存區(qū)了)
如果只 git add 了沒有 git commit(如果連 git add都沒有, 那只能找磁盤數(shù)據(jù)恢復(fù)的方式了), 這就不是僅僅一個(gè) git reflog 就能找回的了。
$ cd .. && rm -rf git-study && mkdir git-study && cd git-study && git init
$ echo 'master message 1' >> master_1.txt
$ git add master_1.txt
$ git commit -m 'first commit'
$ echo 'master message 2' >> master_2.txt
$ git add master_2.txt
$ git commit -m 'No.2 commit'
$ echo 'master message 3' >> master_3.txt
$ git add .
# 查看 log
$ git log -n 2
# 取最新的一次 commit id
$ git reset --hard ee614a48f753479a111723ae7ad926e0750ffa6c
# 查看 status
$ git status
On branch master
nothing to commit, working tree clean
# 查看本地文件
total 16
-rw-r--r-- 1 kino staff 17B 11 24 02:43 master_1.txt
-rw-r--r-- 1 kino staff 17B 11 24 02:43 master_2.txt
# 可以看見文件已經(jīng)丟了
git 提供了 git fsck --lost-found 命令, 他會(huì)通過(guò)一些神奇的方式把歷史操作過(guò)的文件以某種算法算出來(lái)加到.git/lost-found文件夾里,輸出的記錄就像下面這個(gè)樣子。
? git fsck --lost-found
Checking object directories: 100% (256/256), done.
dangling blob adbd4c8bf64367fb685336a67f02c5716dc47d73
這里返回的第一行帶有 blob 的信息,我們可以用 git show來(lái)查看里面的內(nèi)容
$ git show adbd4c8bf64367fb685336a67f02c5716dc47d73
master message 3
# 比如可以將內(nèi)容追加到新文件中
$ git show adbd4c8bf64367fb685336a67f02c5716dc47d73 > master_3.txt
小記: 如果你的提交記錄多的話, git fsck --lost-found 可以看見很多內(nèi)容, 如下
$ git fsck --lost-found
Checking object directories: 100% (256/256), done.
Checking objects: 100% (35559/35559), done.
dangling blob 601e8abff177a0b2f8a31944654c0cdf0dd1f197
dangling tree 6c247c35ae51aa86736f745802bb59b97b6598ee
dangling blob 7a379e6f07391f3bca1fbcc076fcde8f719ffb69
dangling blob c66fa02bf74853789b63615a80998b3fbd3d8823
dangling blob 4996ec43a907f8f6312c3bf137e2f76c7f4c9c9c
dangling commit 69a110054ca792e6b1060d20ec24ddc9710ada4d
dangling blob 87ed1263b56d0a98cd163440f872f135a34b61da
dangling blob aff0bc224d142929e3f82b8855dd1e97d8b3635b
dangling blob eef114f8614a15a11ccfbb7cf5e34302072176e1
dangling blob b50db5dad43e13fde45141039f684be48e293739
dangling blob 820f0136b61394e482fd18e28a7ba81fbb31f688
dangling blob 2d26cd809139b86218d3460c85baed90d018f007
dangling blob 603ca9d770947939d8da7ff3aef3775bb27c427e
dangling blob e54821ed942c6582d01f60b6715e16301cdcfc4d
dangling blob e06be73bb272c7837ab38226c1c1bb13f845574e
dangling blob 399aede4e687465bf7c895251bef685b0de089b6
dangling blob 5ea2239d63a9a119a54a52fde6ebf208a940832a
dangling blob 35ab95c7faf42b7dbbf4e0992527c719ffd4acbd
dangling blob 9bb609de693b78eb1dc0e3dca7a9d684effd3f4a
dangling blob aac499592477199b2630791aecde2db8a608dfa9
dangling commit 10c581dcdf08ea1bed594a359e09698afd4f794e
dangling blob 06eb7790a9f71bf796749940102030c6e9503022
可以看到這里有blob、commit、tree類型的數(shù)據(jù),其實(shí)還有tag等類型的, 這里需要了解下 git 的底層存儲(chǔ)
commit 數(shù)據(jù)結(jié)構(gòu)在每次提交之后都會(huì)生成一個(gè), 當(dāng)我們進(jìn)行 commit 之后, 首先會(huì)創(chuàng)建一個(gè) commit 組件, 之后創(chuàng)建一個(gè) tree 組件, 把所有的文件信息都存在里面, 每個(gè) blob 都代表一個(gè)文件, 都可以在 tree 里面找到。blob 組件并不會(huì)對(duì)文件信息進(jìn)行存儲(chǔ), 而是只對(duì)文件的內(nèi)容進(jìn)行記錄, 文件信息存儲(chǔ)在 tree 里.
5.4 終極大招
如果 5.3 并沒有找到你想要的內(nèi)容, 那只能再去看看最近修改的文件了
$ find .git/objects -type f | xargs ls -lt | sed 3q
-r--r--r-- 1 kino staff 33 11 24 02:43 .git/objects/ad/bd4c8bf64367fb685336a67f02c5716dc47d73
-r--r--r-- 1 kino staff 33 11 24 02:43 .git/objects/cc/6e4eeea4f70e784fade7a18bdba6c28f7642e8
-r--r--r-- 1 kino staff 33 11 24 02:43 .git/objects/24/b6cb352efeff7a2b24b99e8ff814ab1fc2a2fd
使用 git cat-file -t commitid 可以看見是什么類型的
$ git cat-file -t adbd4c8bf64367fb685336a67f02c5716dc47d73
blob
$ git cat-file -t cc6e4eeea4f70e784fade7a18bdba6c28f7642e8
blob
$ git cat-file -t 24b6cb352efeff7a2b24b99e8ff814ab1fc2a2fd
blob
再使用 git cat-file -p commitid 查看內(nèi)容
$ git cat-file -p adbd4c8bf64367fb685336a67f02c5716dc47d73
master message 3
$ git cat-file -p cc6e4eeea4f70e784fade7a18bdba6c28f7642e8
master message 2
$ git cat-file -p 24b6cb352efeff7a2b24b99e8ff814ab1fc2a2fd
master message 1
5.5 git 遷移(保留 commit)
5.5.1 clone 原來(lái)的項(xiàng)目
$ git clone --bare git://github.com/username/project.git
5.5.2 推送到新的gitlab
$ cd project
$ git push --mirror git@example.com/username/newproject.git
會(huì)提示沒有權(quán)限, 在gitlab中把項(xiàng)目的權(quán)限保護(hù)關(guān)掉就好了
5.5.3 本地代碼更換gitlab地址
$ git remote set-url origin git@example.com/username/newproject.git
5.6 git rebase
準(zhǔn)備4個(gè)場(chǎng)景:
merge 時(shí)只有一個(gè)分支變更merge 時(shí)兩個(gè)分支有變更rebase 時(shí)只有一個(gè)分支變更rebase 時(shí)兩個(gè)分支有變更
5.6.1 merge 時(shí)只有一個(gè)分支變更
rm -rf first-project && mkdir first-project && cd first-project
git init
echo "c0" >> README.md
git add README.md
git commit -m "init"
## 創(chuàng)建一個(gè)分支
git checkout -b feature
## 在 master 上添加兩個(gè) commit
git checkout main
echo "c1" >> README.md
git add README.md
git commit -m "c1 commit"
echo "c2" >> README.md
git add README.md
git commit -m "c2 commit"
## feature 合并 master 新增記錄
git checkout feature
git merge main
## 查看日志, 可以看見 feature 分支上已經(jīng)有了 master 的兩個(gè)提交了
git log --graph --pretty=oneline --abbrev-commit
* c001f6f (HEAD -> feature, main) c2 commit
* a4d98be c1 commit
* 7171bfa init
cat README.md
c0
c1
c2
5.6.2 merge 時(shí)兩個(gè)分支有變更
rm -rf first-project && mkdir first-project && cd first-project
git init
echo "c0" >> README.md
git add README.md
git commit -m "init"
## 創(chuàng)建兩個(gè)分支
git checkout -b feature1
git checkout -b feature2
## 在 feature1 上添加兩個(gè) commit
git checkout feature1
echo "c1" >> README.md
git add README.md
git commit -m "c1 commit"
echo "c2" >> README.md
git add README.md
git commit -m "c2 commit"
## 在 feature2 上添加兩個(gè) commit
git checkout feature2
echo "c3" >> README.md
git add README.md
git commit -m "c3 commit"
echo "c4" >> README.md
git add README.md
git commit -m "c4 commit"
## 在 feature1 上添加一個(gè) commit
git checkout feature1
echo "c5" >> README.md
git add README.md
git commit -m "c5 commit"
## 查看兩個(gè)分支的commit時(shí)間
git log feature1
commit a16e20a00329b0a60cbf8f541ff999e065a907b0 (HEAD -> feature1)
Author: kino
Date: Thu Apr 6 23:17:13 2023 +0800
c5 commit
commit bddb67864d6a8e5923618564304090a869dedf68
Author: kino
Date: Thu Apr 6 23:17:02 2023 +0800
c2 commit
commit 4a0978f9892241abd481251ed96f5a7b92199011
Author: kino
Date: Thu Apr 6 23:16:58 2023 +0800
c1 commit
commit cde011b84e70d5dfbd966b91f5d9ab0aeefff25a (master)
Author: kino
Date: Thu Apr 6 23:16:49 2023 +0800
init
git log feature2
commit 02f337014fa6acbdcbcf79d4ecd6668cdd37d6cb (feature2)
Author: kino
Date: Thu Apr 6 23:17:09 2023 +0800
c4 commit
commit e4567ef53ad207ea88cc042140183f8e047a5b69
Author: kino
Date: Thu Apr 6 23:17:06 2023 +0800
c3 commit
commit cde011b84e70d5dfbd966b91f5d9ab0aeefff25a (master)
Author: kino
Date: Thu Apr 6 23:16:49 2023 +0800
init
## 可以看見, feature2 上的兩個(gè) commit 時(shí)間晚于 feature1 的 c2/c3 commit, 但是又早于 feature1 上的 c5 commit
## 現(xiàn)在將 feature1 合并到 feature2
git checkout feature2
git merge feature1
## 沖突提示
Already on 'feature2'
Auto-merging README.md
CONFLICT (content): Merge conflict in README.md
Automatic merge failed; fix conflicts and then commit the result.
## 解決沖突
vim README.md
git add .
git commit
## 再次查看feature2的提交記錄, 發(fā)現(xiàn)多出來(lái)了一個(gè) commit:faaa86d914cce98ab6dd6159ff76a4fe351f809e
## 并且時(shí)間順序是按兩個(gè)分支的時(shí)間排好序的(合并后時(shí)間有序未被打亂)
commit 6f9869531606418e4c40fabb9cfaabfa1425545a (HEAD -> feature2)
Merge: 02f3370 a16e20a
Author: kino
Date: Thu Apr 6 23:20:13 2023 +0800
Merge branch 'feature1' into feature2
commit a16e20a00329b0a60cbf8f541ff999e065a907b0 (feature1)
Author: kino
Date: Thu Apr 6 23:17:13 2023 +0800
c5 commit
commit 02f337014fa6acbdcbcf79d4ecd6668cdd37d6cb
Author: kino
Date: Thu Apr 6 23:17:09 2023 +0800
c4 commit
commit e4567ef53ad207ea88cc042140183f8e047a5b69
Author: kino
Date: Thu Apr 6 23:17:06 2023 +0800
c3 commit
commit bddb67864d6a8e5923618564304090a869dedf68
Author: kino
Date: Thu Apr 6 23:17:02 2023 +0800
c2 commit
commit 4a0978f9892241abd481251ed96f5a7b92199011
Author: kino
Date: Thu Apr 6 23:16:58 2023 +0800
c1 commit
commit cde011b84e70d5dfbd966b91f5d9ab0aeefff25a (master)
Author: kino
Date: Thu Apr 6 23:16:49 2023 +0800
init
5.6.3 rebase 時(shí)只有一個(gè)分支變更
rebase 分支未作出commit
rm -rf first-project && mkdir first-project && cd first-project
git init
echo "c0" >> README.md
git add README.md
git commit -m "init"
## 創(chuàng)建一個(gè)分支
git checkout -b feature
## 在 master 上添加兩個(gè) commit
git checkout master
echo "c1" >> README.md
git add README.md
git commit -m "c1 commit"
echo "c2" >> README.md
git add README.md
git commit -m "c2 commit"
## feature 合并 master 新增記錄
git checkout feature
git rebase master
## 查看日志, 可以看見 feature 分支上已經(jīng)有了 master 的兩個(gè)提交了, 并且指針feature和master同時(shí)指向HEAD
git log --graph --pretty=oneline --abbrev-commit
* 715cf72 (HEAD -> feature, master) c2 commit
* 5f626b8 c1 commit
* 6a2e050 init
5.6.4 rebase 時(shí)兩個(gè)分支有變更
rebase 分支作出commit
rm -rf first-project && mkdir first-project && cd first-project
git init
echo "c0" >> README.md
git add README.md
git commit -m "init"
## 創(chuàng)建一個(gè)分支
git checkout -b feature
## 在 feature 上添加一個(gè) commit
echo "c3" >> README.md
git add README.md
git commit -m "c3 commit"
## 在 master 上添加兩個(gè) commit
git checkout master
echo "c1" >> README.md
git add README.md
git commit -m "c1 commit"
echo "c2" >> README.md
git add README.md
git commit -m "c2 commit"
## 查看 feature 分支的log
git log feature
commit d97013d9428e61d4d97ebe6a67b5c27d1b98c7cb (HEAD -> feature)
Author: kino
Date: Thu Apr 6 23:26:59 2023 +0800
c3 commit
commit fb9a4a69bbb4d187f0f3a94dbf0cb2938f114e62
Author: kino
Date: Thu Apr 6 23:26:55 2023 +0800
init
## 查看 master 分支的log
git log master
commit 0ec71a9b42831756babb31aba75d56e0e73a6c68 (master)
Author: kino
Date: Thu Apr 6 23:27:10 2023 +0800
c2 commit
commit fdf2a2ec1967c0f29e60d65fa285f627e2cd6767
Author: kino
Date: Thu Apr 6 23:27:07 2023 +0800
c1 commit
commit fb9a4a69bbb4d187f0f3a94dbf0cb2938f114e62
Author: kino
Date: Thu Apr 6 23:26:55 2023 +0800
init
## 可以看見 feature 分支上的 c3 commit 時(shí)間早于 master 分支的 c1/c2 commit
## feature 合并 master 新增記錄
git checkout feature
git rebase master
## 提示有沖突, 解決沖突
vim README.md
git add README.md
git rebase --continue
## 再次查看 feature 分支的 log, 發(fā)現(xiàn) c3 commit 時(shí)間早于 master 分支的 c1/c2 commit, 但是排在了最后面(沒按時(shí)間排序)
## 并且, c3 commit 的 commit id 已經(jīng)變了.
## rebase 原理: 一次 rebase 中, 會(huì)拿到 當(dāng)前分支最新的 commit、被 rebase 分支最新的 commit、以及它們最近的一個(gè)父commit,
## 然后將當(dāng)前分支 從父commit到當(dāng)前最新commit 移動(dòng)到被 rebase 分支最新代碼之后(此時(shí)被移動(dòng)過(guò)來(lái)的commit是屬于被重新commit了, 和原來(lái)的已經(jīng)不一樣了)
## 最后將當(dāng)前分支的指針移動(dòng)到最近的地方.
commit e5fd30e03a32d1a902895dfa8ec51e50ba02bd41 (HEAD -> feature)
Author: kino
Date: Thu Apr 6 23:26:59 2023 +0800
c3 commit
commit 0ec71a9b42831756babb31aba75d56e0e73a6c68 (master)
Author: kino
Date: Thu Apr 6 23:27:10 2023 +0800
c2 commit
commit fdf2a2ec1967c0f29e60d65fa285f627e2cd6767
Author: kino
Date: Thu Apr 6 23:27:07 2023 +0800
c1 commit
commit fb9a4a69bbb4d187f0f3a94dbf0cb2938f114e62
Author: kino
Date: Thu Apr 6 23:26:55 2023 +0800
init
## 查看 feature 的log, 也能得出上面說(shuō)的原理
* e5fd30e (HEAD -> feature) c3 commit
* 0ec71a9 (master) c2 commit
* fdf2a2e c1 commit
* fb9a4a6 init
5.6.5 rebase 總結(jié)
rebase 的時(shí)候, 找到當(dāng)前分支和被rebase分支的父commit, 然后找到當(dāng)前分支在父commit之后所有的commit記錄, 把這些 commit 記錄移動(dòng)到被 rebase 分支上去, 這些 commit 記錄已經(jīng)不是原來(lái)的 commit 了(因?yàn)?commit id 已經(jīng)改變了)?;蛘咄ㄋ讈?lái)說(shuō): rebase 就是被rebase分支插入到當(dāng)前分支之前, 例如: 從 master checkout 一個(gè) feature 用作開發(fā), 開發(fā)一段時(shí)間之后, 有人給 master 提交代碼了(如fixbug), 那么我們應(yīng)該 rebase master 到當(dāng)前分支, 當(dāng) master 最新的代碼放到 feature 最前面.
根據(jù)上面說(shuō)的, rebase 是將 被rebase 分支的commit 放到最前面, 所以在后續(xù)開發(fā)中, 如果 feature 分支需要回退版本, 那么這將很好追溯代碼; 如果我們使用 merge 將master 提交的代碼合并到 feature 分支, 那回退版本就可以能把別人提交的代碼也刪掉了.
同樣的, 因?yàn)?rebase 會(huì)讓當(dāng)前分支的 commit 重新生成, 這會(huì)改變分支的歷史, 在 push 到遠(yuǎn)程分支的時(shí)候, 會(huì)提示你的代碼和遠(yuǎn)程分支不一致, 這就需要強(qiáng)制 push 了(git push --force-with-lease origin mybranch), 所以, 千萬(wàn)不要在公共分支上使用 rebase, 歷史被打亂是一件很嚴(yán)重的事情!!!
在公共分支上不要使用 rebase, 應(yīng)該用 merge;功能分支上, 可以選擇 rebase(不介意時(shí)間順序, 把自己的 commit 頂?shù)阶詈?.
5.6.6 rebase 的命令行操作
開啟命令行操作
git rebase -i your_commit_id
如
git rebase -i HEAD~3
之后會(huì)提示很多信息
### 可以選擇的操作
# Commands:
### p: 選擇一個(gè)提交并且應(yīng)用它: pick 111111e c1 first-commit -> 改變分支的 commit 信息為 first-commit,其commit id 是 111111e
# p, pick
# r, reword
# e, edit
# s, squash
# f, fixup [-C | -c]
# commit's log message, unless -C is used, in which case
# keep only this commit's message; -c is same as -C but
# opens the editor
# x, exec
# b, break = stop here (continue rebase later with 'git rebase --continue')
# d, drop
# l, label
# t, reset
# m, merge [-C
# . create a merge commit using the original merge commit's
# . message (or the oneline, if no original merge commit was
# . specified); use -c
#
# These lines can be re-ordered; they are executed from top to bottom.
#
# If you remove a line here THAT COMMIT WILL BE LOST.
#
# However, if you remove everything, the rebase will be aborted.
#
假設(shè)現(xiàn)在有如下 commit 記錄
cd ..
rm -rf first-project && mkdir first-project && cd first-project
git init
echo "c0" >> README.md
git add README.md
git commit -m "init"
echo "c1" >> README.md
git add README.md
git commit -m "c1 commit"
echo "c2" >> README.md
git add README.md
git commit -m "c2 commit"
echo "c3" >> README.md
git add README.md
git commit -m "c3 commit"
echo "c4" >> README.md
git add README.md
git commit -m "c4 commit"
echo "c5" >> README.md
git add README.md
git commit -m "c5 commit"
git log
commit 84a6eefbec1d95b74f75b2f4ce290291bf70ac7d (HEAD -> master)
Author: kino
Date: Fri Apr 7 00:16:51 2023 +0800
c5 commit
commit f7dfd4a23515f8b4c5f35df7f10a0436887de8b9
Author: kino
Date: Fri Apr 7 00:16:50 2023 +0800
c4 commit
commit 9cbec48fce6bf102dc9160a2c60fb04d8038de14
Author: kino
Date: Fri Apr 7 00:16:50 2023 +0800
c3 commit
commit 1d316c48f7879387bee619f68de1c1d635d01350
Author: kino
Date: Fri Apr 7 00:16:50 2023 +0800
c2 commit
commit 3e477718c5c4a00bc708e4e413e79104651e784b
Author: kino
Date: Fri Apr 7 00:16:50 2023 +0800
c1 commit
commit e8e267817444fb8601ddd76ac98af570cfb546eb
Author: kino
Date: Fri Apr 7 00:16:50 2023 +0800
init
squash
我想要將 c4 commit 和 c3 commit 合并成一個(gè)commit
git rebase -i e8e267817444fb8601ddd76ac98af570cfb546eb
pick 3e47771 c1 commit
pick 1d316c4 c2 commit
pick 9cbec48 c3 commit
squash f7dfd4a c4 commit
pick 84a6eef c5 commit
## 修改合并的commit信息
## 查看 log
commit 779c9bf0f7503a0b7020a447666c7ef3c241b884 (HEAD -> master)
Author: kino
Date: Fri Apr 7 00:19:01 2023 +0800
c5 commit
commit 0e4b3536cb998f3ffab91746954366915d9eb360
Author: kino
Date: Fri Apr 7 00:19:01 2023 +0800
c3 commit
c4 commit
commit 348af55dbbb9472ca132ff6ad0aa159efe9d6fca
Author: kino
Date: Fri Apr 7 00:19:01 2023 +0800
c2 commit
commit 282990a0baf322e25c49c0245fecb9ff4bd0bab6
Author: kino
Date: Fri Apr 7 00:19:01 2023 +0800
c1 commit
commit 0ac0f9228c9be4b02632e01849036d8eeee73378
Author: kino
Date: Fri Apr 7 00:19:01 2023 +0800
init
## 查看 0e4b353 變更了哪些東西, 可以看見, 本次 commit, 修改了 README.md 文件, 添加了 c3/c4 兩行代碼
commit 0e4b3536cb998f3ffab91746954366915d9eb360
Author: kino
Date: Fri Apr 7 00:19:01 2023 +0800
c3 commit
c4 commit
diff --git a/README.md b/README.md
index c3f2bc9..d226868 100644
--- a/README.md
+++ b/README.md
@@ -1,3 +1,5 @@
c0
c1
c2
+c3
+c4
fixup
也可以使用 fixup 代替 squash, fixup 不會(huì)保留合并的的提交信息, 可以使用此操作將一個(gè)小的提交合并到之前的提交中
git rebase -i 0ac0f9228c9be4b02632e01849036d8eeee73378
pick fdf2a2e c1 commit
pick 0ec71a9 c2 commit
pick e5fd30e c3 commit
fixup 69799d0 c4 commit
pick cb1017b c5 commit
edit
當(dāng)然還可以修改 commit 信息
git rebase -i 0ac0f9228c9be4b02632e01849036d8eeee73378
pick fdf2a2e c1 commit
pick 0ec71a9 c2 commit
pick e5fd30e c3 commit
edit 69799d0 c4 commit
pick cb1017b c5 commit
# 執(zhí)行以下命令開始操作(可以執(zhí)行多次)
git commit --amend
## 填寫 commit 信息
## 修改到滿意之后, 執(zhí)行以下命令生效
git rebase --continue
reword
修改 commit 信息也可以直接使用 reword, 這將直接開始修改
git rebase -i 0ac0f9228c9be4b02632e01849036d8eeee73378
pick fdf2a2e c1 commit
pick 0ec71a9 c2 commit
pick e5fd30e c3 commit
reword 69799d0 c4 commit
pick cb1017b c5 commit
drop
除此之外, 還可以刪除某個(gè) commit
git rebase -i 0ac0f9228c9be4b02632e01849036d8eeee73378
pick fdf2a2e c1 commit
pick 0ec71a9 c2 commit
pick e5fd30e c3 commit
drop 69799d0 c4 commit
pick cb1017b c5 commit
5.7 cherry-pick
git cherry-pick 命令用于將指定的提交(commit)應(yīng)用于當(dāng)前分支。這個(gè)命令可以方便地將其他分支或者提交的修改應(yīng)用到當(dāng)前分支中,而無(wú)需將整個(gè)分支合并。
rm -rf first-project && mkdir first-project && cd first-project
git init
echo "c0" >> README.md
git add README.md
git commit -m "init"
## 創(chuàng)建兩個(gè)分支
git checkout -b feature1
git checkout -b feature2
## 在 feature1 上添加兩個(gè) commit
git checkout feature1
echo "c1" >> README.md
git add README.md
git commit -m "c1 commit"
echo "c2" >> README.md
git add README.md
git commit -m "c2 commit"
## 在 feature2 上添加兩個(gè) commit
git checkout feature2
echo "c3" >> README.md
git add README.md
git commit -m "c3 commit"
echo "c4" >> README.md
git add README.md
git commit -m "c4 commit"
git log feature1
commit 762ae4b983da0bff873877779cd74e1aa8d10f88 (feature1)
Author: kino
Date: Fri Apr 7 01:07:24 2023 +0800
c2 commit
commit 32fd3337cdf54589d9e6c46626886cd3c8936fa1
Author: kino
Date: Fri Apr 7 01:07:24 2023 +0800
c1 commit
commit 526925ca652065f75129e49f25090d58d33ce31f (master)
Author: kino
Date: Fri Apr 7 01:07:24 2023 +0800
init
git log feature2
commit f956ab14791d3d3718a57ddd8f062178f808cf44 (HEAD -> feature2)
Author: kino
Date: Fri Apr 7 01:07:24 2023 +0800
c4 commit
commit b0666c02180c1bddf60190e14bb9391379b54598
Author: kino
Date: Fri Apr 7 01:07:24 2023 +0800
c3 commit
commit 526925ca652065f75129e49f25090d58d33ce31f (master)
Author: kino
Date: Fri Apr 7 01:07:24 2023 +0800
init
現(xiàn)在講 feature1 分支上的 762ae4b983da0bff873877779cd74e1aa8d10f88 應(yīng)用到 feature2 上
git checkout feature2
git cherry-pick 762ae4b983da0bff873877779cd74e1aa8d10f88
如果有沖突, 需要解決沖突后, 使用 git add 添加到暫存區(qū), 然后使用 git cherry-pick --continue 繼續(xù) cherry-pick 操作, 直到完成.
注意: 使用 git cherry-pick 命令將提交應(yīng)用到當(dāng)前分支時(shí),也可能會(huì)引入新的問(wèn)題,因此在使用該命令時(shí)需要謹(jǐn)慎。
柚子快報(bào)邀請(qǐng)碼778899分享:java git常用操作
精彩內(nèi)容
本文內(nèi)容根據(jù)網(wǎng)絡(luò)資料整理,出于傳遞更多信息之目的,不代表金鑰匙跨境贊同其觀點(diǎn)和立場(chǎng)。
轉(zhuǎn)載請(qǐng)注明,如有侵權(quán),聯(lián)系刪除。