git详解(三)回退操作
2016-11-27 21:40
162 查看
git详解(三)回退操作
摘要: 在我们使用git修改文件需要回到修改之前的状态时,就需要git的回退操作,回退操作对于我们很重要,本文主要介绍关于git回退操作的内容。包括git reset ,git checkout。通过本文,我们可以对git的回退操作有一个很好的理解。关键字: 回退,reset, checkout
git详解三回退操作
git logreflog
git reset
git checkout
conclusion
1. git log/reflog
master这个引用指向我们最新的提交,类似于一个游标,通过git reset可以对游标进行修改。fox@fox:~/Documents/demo$ git log --oneline 539d895 add new.log ba7f561 commit 0e94145 add test.txt fox@fox:~/Documents/demo$ git reset --hard ba7f561 fox@fox:~/Documents/demo$ git log --oneline ba7f561 commit 0e94145 add test.txt
发现在执行git reset的时候,master发生了变化,git log也随之进行了变化,那么问题来了,是不是我们只能git reset 历史commit呢?也就是这样的游标只能往后,不能往前,其实不是的。我们继续看一下提交log。
fox@fox:~/Documents/demo$ cat .git/logs/refs/heads/master 0000000000000000000000000000000000000000 0e94145e01eb5da2420dd8a47d103aeab1dff44b fox <leehaoran111@163.com> 1476806519 +0800 commit (initial): add test.txt 0e94145e01eb5da2420dd8a47d103aeab1dff44b ba7f561a2798f2b41a7131888bdbc58531ba89c5 fox <leehaoran111@163.com> 1478435045 +0800 commit: commit ba7f561a2798f2b41a7131888bdbc58531ba89c5 d4c1f0765b0b58ce464d95989f2ebfe4094f4f54 fox <leehaoran111@163.com> 1478439077 +0800 commit: ok d4c1f0765b0b58ce464d95989f2ebfe4094f4f54 ba7f561a2798f2b41a7131888bdbc58531ba89c5 fox <leehaoran111@163.com> 1480241004 +0800 reset: moving to HEAD^ ba7f561a2798f2b41a7131888bdbc58531ba89c5 539d8955e8820776f914d93f5778e2025884f0a6 fox <leehaoran111@163.com> 1480241093 +0800 commit: add new.log 539d8955e8820776f914d93f5778e2025884f0a6 ba7f561a2798f2b41a7131888bdbc58531ba89c5 fox <leehaoran111@163.com> 1480241299 +0800 reset: moving to HEAD^ ba7f561a2798f2b41a7131888bdbc58531ba89c5 539d8955e8820776f914d93f5778e2025884f0a6 fox <leehaoran111@163.com> 1480242249 +0800 reset: moving to 539d895 539d8955e8820776f914d93f5778e2025884f0a6 ba7f561a2798f2b41a7131888bdbc58531ba89c5 fox <leehaoran111@163.com> 1480242306 +0800 reset: moving to ba7f561 fox@fox:~/Documents/demo$ git cat-file -p 539d8955 tree b5f005e70497d197ba637c9576621beda3ec7233 parent ba7f561a2798f2b41a7131888bdbc58531ba89c5 author fox <leehaoran111@163.com> 1480241093 +0800 committer fox <leehaoran111@163.com> 1480241093 +0800 add new.log fox@fox:~/Documents/demo$ git cat-file -p b5f005e 100644 blob 6594dfffc7a1e8b880c02eb5f97d11caef98a6d0 new.log 100644 blob 7aeee4f72cc77cc564fcc3aa7fd03caea3542fcb test.txt fox@fox:~/Documents/demo$ git cat-file -p 6594dfff git reset demo
发现可以在git 的提交log中找到历史的master commit id. 也就是539d8955e88。
通过git reset 539d8955e88 会发现new.log又回来了。
fox@fox:~/Documents/demo$ git reset --hard 539d8955e HEAD is now at 539d895 add new.log fox@fox:~/Documents/demo$ ll total 20 drwxrwxr-x 3 fox fox 4096 11月 27 18:35 ./ drwxr-xr-x 10 fox fox 4096 11月 6 22:06 ../ drwxrwxr-x 8 fox fox 4096 11月 27 18:35 .git/ -rw-rw-r-- 1 fox fox 15 11月 27 18:35 new.log -rw-rw-r-- 1 fox fox 45 11月 6 21:18 test.txt
前面log文件中记录的master变化是顺序的,也就是最新的在最下面,git reflog可以看到倒序的变化,这样方便我们查看。
fox@fox:~/Documents/demo$ git reflog 539d895 HEAD@{0}: reset: moving to 539d8955e ba7f561 HEAD@{1}: reset: moving to ba7f561a 539d895 HEAD@{2}: reset: moving to 539d8955e ba7f561 HEAD@{3}: reset: moving to ba7f56 539d895 HEAD@{4}: reset: moving to 539d8955e8 ba7f561 HEAD@{5}: reset: moving to ba7f561 539d895 HEAD@{6}: reset: moving to 539d895 ba7f561 HEAD@{7}: reset: moving to HEAD^ 539d895 HEAD@{8}: commit: add new.log ba7f561 HEAD@{9}: reset: moving to HEAD^ d4c1f07 HEAD@{10}: commit: ok ba7f561 HEAD@{11}: commit: commit 0e94145 HEAD@{12}: commit (initial): add test.txt
这样,我们可以通过git log 和git reflog就可以查看之前之后的提交commit id.
2. git reset
在知道了怎样查找commit id之后,我们就可以借助git reset来按照我们的需求切换commit id了。git reset可以加路径也可以不加路径,加路径表示更改一个文件。
git reset [--soft | --mixed [-N] | --hard | --merge | --keep] [-q] [<commit>]
git reset 后面加–soft,–hard,–mixed是有区别的,这也经常会用到,我们举一个例子看一下区别
step 1:let us create a file demo.c fox@fox:~/Documents/demo$ git st On branch master Untracked files: (use "git add <file>..." to include in what will be committed) demo.c nothing added to commit but untracked files present (use "git add" to track) fox@fox:~/Documents/demo$ git add * fox@fox:~/Documents/demo$ git st On branch master Changes to be committed: (use "git reset HEAD <file>..." to unstage) new file: demo.c fox@fox:~/Documents/demo$ git reset --hard HEAD HEAD is now at 539d895 add new.log fox@fox:~/Documents/demo$ git st On branch master nothing to commit, working directory clean fox@fox:~/Documents/demo$ ll total 20 drwxrwxr-x 3 fox fox 4096 11月 27 19:02 ./ drwxr-xr-x 10 fox fox 4096 11月 6 22:06 ../ drwxrwxr-x 8 fox fox 4096 11月 27 19:02 .git/ -rw-rw-r-- 1 fox fox 15 11月 27 18:35 new.log -rw-rw-r-- 1 fox fox 45 11月 6 21:18 test.txt 发现用--hard时,staging和工作区的修改和HEAD一样了。同时工作区demo.c也不见了。这时要恢复demo.c就比较麻烦了,需要在objects里面挨个找了。 我们新建一个demo.c,继续看--mixed fox@fox:~/Documents/demo$ echo "i am demo.c" >demo.c fox@fox:~/Documents/demo$ git st On branch master Untracked files: (use "git add <file>..." to include in what will be committed) demo.c nothing added to commit but untracked files present (use "git add" to track) fox@fox:~/Documents/demo$ git add * fox@fox:~/Documents/demo$ git st On branch master Changes to be committed: (use "git reset HEAD <file>..." to unstage) new file: demo.c fox@fox:~/Documents/demo$ git reset --mixed HEAD fox@fox:~/Documents/demo$ git st On branch master Untracked files: (use "git add <file>..." to include in what will be committed) demo.c nothing added to commit but untracked files present (use "git add" to track) 可以看到--mixed用mstaer中的内容覆盖staging中的内容,但不修改工作区的修改。而且--mixed是默认的选项。 能猜到,--soft的话就是仅仅修改HEAD指向的commit id,不影响staging和工作区。
3 git checkout
git reset可以在当前分支中切换commit id,但是当我们想到切换HEAD指向的分支时该怎么办呢?我们知道在每一次git commit的时候,都是当前的HEAD指向的commit id会成为父提交。这时候就需要用到checkout.checkout也是经常会用到的一个命令。git checkout [-q] [-f] [-m] [<branch>] git checkout [-q] [-f] [-m] --detach [<branch>] git checkout [-q] [-f] [-m] [--detach] <commit> git checkout [-q] [-f] [-m] [[-b|-B|--orphan] <new_branch>] [<start_point>] git checkout [-f|--ours|--theirs|-m|--conflict=<style>] [<tree-ish>] [--] <paths>... git checkout [-p|--patch] [<tree-ish>] [--] [<paths>...] checkout有以下用法: 用法一:分支切换: fox@fox:~/Documents/demo$ git br fixbug * master fox@fox:~/Documents/demo$ git co fixbug Switched to branch 'fixbug' fox@fox:~/Documents/demo$ git br * fixbug master 用法二:显示staging和版本库的区别: fox@fox:~/Documents/demo$ ll total 16 drwxrwxr-x 3 fox fox 4096 11月 27 21:23 ./ drwxr-xr-x 10 fox fox 4096 11月 6 22:06 ../ drwxrwxr-x 8 fox fox 4096 11月 27 21:24 .git/ -rw-rw-r-- 1 fox fox 45 11月 6 21:18 test.txt fox@fox:~/Documents/demo$ echo "add more" >> test.txt fox@fox:~/Documents/demo$ git st On branch fixbug Changes not staged for commit: (use "git add <file>..." to update what will be committed) (use "git checkout -- <file>..." to discard changes in working directory) modified: test.txt no changes added to commit (use "git add" and/or "git commit -a") fox@fox:~/Documents/demo$ git add test.txt fox@fox:~/Documents/demo$ git st On branch fixbug Changes to be committed: (use "git reset HEAD <file>..." to unstage) modified: test.txt fox@fox:~/Documents/demo$ git co M test.txt 用法三:用其它分支的文件代替本分支staging和工作区的文件: fox@fox:~/Documents/demo$ git cat-file -p master:new.log git reset demo fox@fox:~/Documents/demo$ ll total 16 drwxrwxr-x 3 fox fox 4096 11月 27 21:28 ./ drwxr-xr-x 10 fox fox 4096 11月 6 22:06 ../ drwxrwxr-x 8 fox fox 4096 11月 27 21:28 .git/ -rw-rw-r-- 1 fox fox 45 11月 27 21:28 test.txt fox@fox:~/Documents/demo$ git co master new.log fox@fox:~/Documents/demo$ git st On branch fixbug Changes to be committed: (use "git reset HEAD <file>..." to unstage) new file: new.log fox@fox:~/Documents/demo$ cat new.log git reset demo 用法四: 撤销工作区的修改: fox@fox:~/Documents/demo$ echo "retort some demo" >> test.txt fox@fox:~/Documents/demo$ git st On branch fixbug Changes not staged for commit: (use "git add <file>..." to update what will be committed) (use "git checkout -- <file>..." to discard changes in working directory) modified: test.txt no changes added to commit (use "git add" and/or "git commit -a") fox@fox:~/Documents/demo$ git co . fox@fox:~/Documents/demo$ git st On branch fixbug nothing to commit, working directory clean