x查看历史提交的目录树 git ls-tree<tree-ish><paths> 示例:git ls-tree 776c5c9 README
git ls-tree -r refs/tags/D REANDME
整个工作区切换到历史版本 git checkout <commit> git checkout HEAD^^
检出某文件的历史版本 git checkout <commit> --<paths> git checkout refs/tags/D README
git checkout 776c5c9 REANDME
检出某文件的历史版本到其他文件名git show <commit>;<file> new_name git show 887113d;README>README.OLD
xxxxxxxxxx
为示例方便我创建以下仓库。
git clone ssh://xwx496887@10.148.192.216:29418/ST/mytest
1.修补式提交,git commit --amend
jagent@ubuntu:~/xin/mytest$ git log --oneline
7c4368e begin
jagent@ubuntu:~/xin/mytest$ touch test.txt
jagent@ubuntu:~/xin/mytest$ echo "helloworld" >> test.txt
jagent@ubuntu:~/xin/mytest$ git add -A
jagent@ubuntu:~/xin/mytest$ git commit -m "error"
[master 7ecd16f] error
1 file changed, 1 insertion(+)
create mode 100644 test.txt
jagent@ubuntu:~/xin/mytest$ git log --oneline
7ecd16f error
7c4368e begin
jagent@ubuntu:~/xin/mytest$ echo "helloworld111" >> test.txt
jagent@ubuntu:~/xin/mytest$ cat test.txt
helloworld
helloworld111
jagent@ubuntu:~/xin/mytest$ git add test.txt
jagent@ubuntu:~/xin/mytest$ git commit --amend -m "fixed"
[master bfa3d09] fixed
1 file changed, 1 insertion(+)
create mode 100644 test.txt
jagent@ubuntu:~/xin/mytest$ git log --oneline
bfa3d09 fixed
7c4368e begin
从上面可以看出来,,在最新的提交基础再次提交,重新生成了一次提交,但是commit对象变了但是次数没变
多部撤销git reset --soft <commitID>意思是回到commitID提交的时候的状态,暂存区有需要提交到库上的文件
jagent@ubuntu:~/xin/mytest$ git log --stat
commit 84a3ac3b44bb69c54d94d19c13e839c3e8eb6eb8
Author: xwx496887 <xwx496887@notesmail.huawei.com>
Date: Tue Nov 10 14:26:59 2020 +0800
xxxx
test.txt | 1 +
test1.txt | 1 +
2 files changed, 2 insertions(+)
commit bfa3d094026e7c98e815fd3368f6b4947236e31d
Author: xwx496887 <xwx496887@notesmail.huawei.com>
Date: Tue Nov 10 14:20:38 2020 +0800
fixed
test.txt | 1 +
1 file changed, 1 insertion(+)
commit 7c4368e8ac273bcd4b017429226af5ffc3b0ce74
Author: xwx496887 <xwx496887@notesmail.huawei.com>
Date: Tue Nov 3 14:35:41 2020 +0800
begin
README.md | 1 +
1 file changed, 1 insertion(+)
jagent@ubuntu:~/xin/mytest$ git reset --soft 7c4368e8ac273bcd4b017429226af5ffc3b0ce74
jagent@ubuntu:~/xin/mytest$ git status
On branch master
Your branch is behind 'origin/master' by 1 commit, and can be fast-forwarded.
(use "git pull" to update your local branch)
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
new file: test.txt
new file: test1.txt
从上面可以看出来回退了2次提交,并且2次提交的文件都回退到暂存区
git cherry-pick 就是获取commitid的那次提交
示例:
jagent@ubuntu:~/xin/mytest$ git tag F
jagent@ubuntu:~/xin/mytest$ git tag E HEAD^
jagent@ubuntu:~/xin/mytest$ git tag D HEAD^^
jagent@ubuntu:~/xin/mytest$ git tag C HEAD^^^
jagent@ubuntu:~/xin/mytest$ git tag B HEAD^4
fatal: Failed to resolve 'HEAD^4' as a valid ref.
jagent@ubuntu:~/xin/mytest$ git tag B HEAD~4
jagent@ubuntu:~/xin/mytest$ git tag A HEAD~5
jagent@ubuntu:~/xin/mytest$ git log --oneline --decorate -6
da9b181 (HEAD, tag: F, master) 6.txt
fceb03f (tag: E) 5.txt
4015ce2 (tag: D) 4.txt
5498b1b (tag: C) 3.txt
830d0ab (tag: B) 2.txt
f54157d (tag: A) 1.txt
干掉tag.D:
jagent@ubuntu:~/xin/mytest$ git checkout C
Note: checking out 'C'.
You are in 'detached HEAD' state. You can look around, make experimental
changes and commit them, and you can discard any commits you make in this
state without impacting any branches by performing another checkout.
If you want to create a new branch to retain commits you create, you may
do so (now or later) by using -b with the checkout command again. Example:
git checkout -b new_branch_name
HEAD is now at c36df4f... 3.txt
jagent@ubuntu:~/xin/mytest$ git cherry-pick
A B C D E F HEAD master ORIG_HEAD origin/HEAD origin/master
jagent@ubuntu:~/xin/mytest$ git cherry-pick master^
[detached HEAD adee8bd] 5.txt
1 file changed, 1 insertion(+)
create mode 100644 5.txt
jagent@ubuntu:~/xin/mytest$ git cherry-pick master
[detached HEAD 12a7c73] 6.txt
1 file changed, 1 insertion(+)
create mode 100644 6.txt
jagent@ubuntu:~/xin/mytest$ git log --oneline
12a7c73 6.txt
adee8bd 5.txt
c36df4f 3.txt
9b99708 2.txt
1f371f0 1.txt
7c4368e begin
jagent@ubuntu:~/xin/mytest$ git log --oneline --decorate
12a7c73 (HEAD) 6.txt
adee8bd 5.txt
c36df4f (tag: C) 3.txt
9b99708 (tag: B) 2.txt
1f371f0 (tag: A) 1.txt
7c4368e (origin/master, origin/HEAD) begin
jagent@ubuntu:~/xin/mytest$ git checkout master
Warning: you are leaving 2 commits behind, not connected to
any of your branches:
12a7c73 6.txt
adee8bd 5.txt
If you want to keep them by creating a new branch, this may be a good time
to do so with:
git branch new_branch_name 12a7c73
Switched to branch 'master'
Your branch is ahead of 'origin/master' by 6 commits.
(use "git push" to publish your local commits)
jagent@ubuntu:~/xin/mytest$ git reflog
f2af943 HEAD@{0}: checkout: moving from 12a7c732980ace5d52a9ae78964dba871d76b057 to master
12a7c73 HEAD@{1}: cherry-pick: 6.txt
adee8bd HEAD@{2}: cherry-pick: 5.txt
c36df4f HEAD@{3}: checkout: moving from master to C
f2af943 HEAD@{4}: commit: 6.txt
19eac6b HEAD@{5}: commit: 5.txt
f855404 HEAD@{6}: commit: 4.txt
c36df4f HEAD@{7}: commit: 3.txt
9b99708 HEAD@{8}: commit: 2.txt
1f371f0 HEAD@{9}: commit: 1.txt
7c4368e HEAD@{10}: reset: moving to 7c4368e8ac273bcd4b017429226af5ffc3b0ce74
19d7bf9 HEAD@{11}: clone: from ssh://xwx496887@10.148.192.216:29418/ST/mytest
jagent@ubuntu:~/xin/mytest$ git reset --hard HEAD@{1}
HEAD is now at 12a7c73 6.txt
jagent@ubuntu:~/xin/mytest$ git branch
* master
jagent@ubuntu:~/xin/mytest$ git log --oneline
12a7c73 6.txt
adee8bd 5.txt
c36df4f 3.txt
9b99708 2.txt
1f371f0 1.txt
7c4368e begin
上面执行了cherry-pick操作,就是获取commitid的那次提交
xxxxxxxxxx
git rebase是对提交执行便基操作,即可以实现将指定范围的提交"嫁接"到另外一个提交之上,git merge与git rebase区别?
常用命令行格式:
用法1: git rebase --onto <newbase> <since> <till>
用法2: git rebase --onto <newbase> <since>
用法3: git rebase <since > <till>
用法4: git rebase <since>
用法5:git rebase -i
用法6:git rebase --continue
用法7: git rebase --skip
用法8:git rebase --abort
用法6.7.8都是变基运行过程被终端时可采取的命令---继续变基或终止等。
用法6是在变基遇到冲突而暂停的情况下,先完成冲突解决(添加到暂存区,不提交),然后再恢复变基操作的时候使用该命令
用法7是再变基遇到冲突而暂定的情况下,跳过当前提交的时候使用
用法8是再变基遇到冲突而暂定的情况下,终止变基操作,回到之前的分支时候使用
而前四个用法如果把省略的参数不上,和用法1就基本一致了。
git rebase命令
git rebase --onto <newbase> <since> <till>
变基操作的过程:
1.首先会执行git checkout切换<till>
因为会切换<till>,因此如果<till>指向的不是一个分支(如master),则变基操作是再detached HEAD(分离头指针)状态进行的,当变基结束后,对master分支执行重置以实现变基结果再分支中生效。
2.将<since>..<till>所表示的提交范围写到一个临时文件中。
<since>..<till>的范围,左开右闭
3.将当前分支强制重置(git reset --hard)到<newbase>.
4.从保存再临时文件中的列表中,将提交逐一按顺序重新提交到重置之后的分支上
5.如果遇过提交已经再分支中包含,则跳过该提交。
6.如果再提交过程遇到冲突,则变基过程暂停,用户解决冲突后,执行git rebase --continue继续变基操作。或者执行git rebese --skip跳过此提交。或者执行giut rebase --abort就此终止变基操作切换到变基前的分支上。
1.干掉D
jagent@ubuntu:~/xin/mytest$ git log --oneline --decorate
f2af943 (HEAD, tag: F, master) 6.txt
19eac6b (tag: E) 5.txt
f855404 (tag: D) 4.txt
c36df4f (tag: C) 3.txt
9b99708 (tag: B) 2.txt
1f371f0 (tag: A) 1.txt
7c4368e (origin/master, origin/HEAD) begin
jagent@ubuntu:~/xin/mytest$ git rebase --onto C D F
First, rewinding head to replay your work on top of it...
Applying: 5.txt
Applying: 6.txt
jagent@ubuntu:~/xin/mytest$ git branch
* (detached from refs/heads/master)
master
jagent@ubuntu:~/xin/mytest$ git checkout master
Warning: you are leaving 2 commits behind, not connected to
any of your branches:
a130b8f 6.txt
b300c36 5.txt
If you want to keep them by creating a new branch, this may be a good time
to do so with:
git branch new_branch_name a130b8f
Switched to branch 'master'
Your branch is ahead of 'origin/master' by 6 commits.
(use "git push" to publish your local commits)
jagent@ubuntu:~/xin/mytest$ git reflog
f2af943 HEAD@{0}: checkout: moving from a130b8f1a1bf341dd34be54cbd43de3b0008d571
a130b8f HEAD@{1}: rebase: 6.txt
b300c36 HEAD@{2}: rebase: 5.txt
c36df4f HEAD@{3}: rebase: checkout C
f2af943 HEAD@{4}: reset: moving to HEAD@{9}
8c54609 HEAD@{5}: merge f855404: Merge made by the 'recursive' strategy.
12a7c73 HEAD@{6}: reset: moving to HEAD@{2}
f2af943 HEAD@{7}: reset: moving to HEAD@{2}
213376e HEAD@{8}: merge f2af943: Merge made by the 'recursive' strategy.
12a7c73 HEAD@{9}: reset: moving to HEAD@{1}
f2af943 HEAD@{10}: checkout: moving from 12a7c732980ace5d52a9ae78964dba871d76b05
12a7c73 HEAD@{11}: cherry-pick: 6.txt
adee8bd HEAD@{12}: cherry-pick: 5.txt
c36df4f HEAD@{13}: checkout: moving from master to C
f2af943 HEAD@{14}: commit: 6.txt
19eac6b HEAD@{15}: commit: 5.txt
f855404 HEAD@{16}: commit: 4.txt
c36df4f HEAD@{17}: commit: 3.txt
9b99708 HEAD@{18}: commit: 2.txt
1f371f0 HEAD@{19}: commit: 1.txt
7c4368e HEAD@{20}: reset: moving to 7c4368e8ac273bcd4b017429226af5ffc3b0ce74
19d7bf9 HEAD@{21}: clone: from ssh://xwx496887@10.148.192.216:29418/ST/mytest
jagent@ubuntu:~/xin/mytest$ git reset --hard HEAD@{1}
HEAD is now at a130b8f 6.txt
jagent@ubuntu:~/xin/mytest$ git branch
* master
jagent@ubuntu:~/xin/mytest$ git log --oneline --decorate
a130b8f (HEAD, master) 6.txt
b300c36 5.txt
c36df4f (tag: C) 3.txt
9b99708 (tag: B) 2.txt
1f371f0 (tag: A) 1.txt
7c4368e (origin/master, origin/HEAD) begin
使用 git rebase -i干掉D
jagent@ubuntu:~/xin/mytest$ git rebase -i C
去掉D的提交#pick f855404 4.txt
pick 19eac6b 5.txt
pick f2af943 6.txt
# Rebase c36df4f..f2af943 onto c36df4f
#
# 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
#
# 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.
#
# Note that empty commits are commented out
Successfully rebased and updated refs/heads/master
jagent@ubuntu:~/xin/mytest$ git log --oneline --decorate
3cf8b56 (HEAD, master) 6.txt
1d8ce87 5.txt
c36df4f (tag: C) 3.txt
9b99708 (tag: B) 2.txt
1f371f0 (tag: A) 1.txt
7c4368e (origin/master, origin/HEAD) begin
已完成变基操作
融入CD提交
jagent@ubuntu:~/xin/mytest$ git log --oneline --decorate
f2af943 (HEAD, tag: F, master) 6.txt
19eac6b (tag: E) 5.txt
f855404 (tag: D) 4.txt
c36df4f (tag: C) 3.txt
9b99708 (tag: B) 2.txt
1f371f0 (tag: A) 1.txt
7c4368e (origin/master, origin/HEAD) begin
pick c36df4f 3.txt
squash f855404 4.txt
pick 19eac6b 5.txt
pick f2af943 6.txt
jagent@ubuntu:~/xin/mytest$ git rebase -i B
# Rebase 9b99708..f2af943 onto 9b99708
#
# 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
#
# 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.
#
# Note that empty commits are commented out
[detached HEAD 23c7526] 3.txt
2 files changed, 2 insertions(+)
create mode 100644 3.txt
create mode 100644 4.txt
Successfully rebased and updated refs/heads/master.
jagent@ubuntu:~/xin/mytest$ git log --oneline --decorate
bf78fe3 (HEAD, master) 6.txt
dbecbf7 5.txt
23c7526 3.txt
9b99708 (tag: B) 2.txt
1f371f0 (tag: A) 1.txt
7c4368e (origin/master, origin/HEAD) begin
jagent@ubuntu:~/xin/mytest$ git cat-file -p 23c7526
tree 797646557b8c9dcd342963624a245be239edc723
parent 9b997088590b78d1526f9a03c53c12da66ab6e10
author xwx496887 <xwx496887@notesmail.huawei.com> 1604997557 +0800
committer xwx496887 <xwx496887@notesmail.huawei.com> 1605007983 +0800
3.txt
4.txt
将需要合并的文件pick改成squash
xxxxxxxxxx
jagent@ubuntu:~/xin/mytest$ git log --oneline --decorate
f2af943 (HEAD, tag: F, master) 6.txt
19eac6b (tag: E) 5.txt
f855404 (tag: D) 4.txt
c36df4f (tag: C) 3.txt
9b99708 (tag: B) 2.txt
1f371f0 (tag: A) 1.txt
7c4368e (origin/master, origin/HEAD) begin
丢弃掉C以前历史提交
第一种:
jagent@ubuntu:~/xin/mytest$ git cat-file -p C{tree}
fatal: Not a valid object name C{tree}
jagent@ubuntu:~/xin/mytest$ git cat-file -p C^{tree}
100644 blob b4de3947675361a7770d29b8982c407b0ec6b2a0 1.txt
100644 blob 2bd5a0a98a36cc08ada88b804d3be047e6aa5b8a 2.txt
100644 blob bb95160cb6e07358f54a28a208ae41e69889c97b 3.txt
100644 blob 09567e828d6c4e7fe358df25ce19966c0a6b273a README.md
jagent@ubuntu:~/xin/mytest$ echo "commit freom tree of tags C" | git commit-tree C^{tree}
ab8ca0a46d053a35f66e479ef818dd39de8a5bc4
jagent@ubuntu:~/xin/mytest$ git log --pretty=raw ab8ca0a46d05
commit ab8ca0a46d053a35f66e479ef818dd39de8a5bc4
tree a9391b3c6d52a8e5fd7f82e107e5f9ce79bd507d
author xwx496887 <xwx496887@notesmail.huawei.com> 1605061567 +0800
committer xwx496887 <xwx496887@notesmail.huawei.com> 1605061567 +0800
commit freom tree of tags C
jagent@ubuntu:~/xin/mytest$
第二种:使用git hash-object命令
git cat-file commit C^0
git cat-file commit A^0 | sed -e '/^parent/ d' >tmpfile
git hash-object -t commit -w --tmpfile
ab8ca0a46d05
git log --pretty=raw ab8ca0a46d05
最终执行变基操作:
jagent@ubuntu:~/xin/mytest$ git rebase --onto ab8ca0a46d05 C master
First, rewinding head to replay your work on top of it...
Applying: 4.txt
Applying: 5.txt
Applying: 6.txt
jagent@ubuntu:~/xin/mytest$ git log --oneline --decorate
f8e17a9 (HEAD, master) 6.txt
b978762 5.txt
139c2c7 4.txt
ab8ca0a commit freom tree of tags C
jagent@ubuntu:~/xin/mytest$ ll
total 40
在不改变这个提交的前提下撤销对其的修改,用到git revert <commitID>/HEAD,意思是撤销提交修改,但是保留了历史提交信息