Merge tool is a GUI that steps you through each conflict, and you get to choose how to merge. Sometimes it requires a bit of hand editing afterwards, but usually it’s enough by itself. It is much better than doing the whole thing by hand certainly.
$ git pull error: Your local changes to the following files would be overwritten by merge: /there/is/a/conflict/file Please, commit your changes or stash them before you can merge.
Stashing takes the dirty state of your working directory – that is, your modified tracked files and staged changes – and saves it on a stack of unfinished changes that you can reapply at any time.
1 pick dc6baf3 本地分支提交的版本 2 pick 915fe84 先被推送到远程分支的版本 3 4 # Rebase 1ff20826..61527529 onto 1ff20826 (2 commands) 5 # 6 # Commands: 7 # p, pick = use commit 8 # r, reword = use commit, but edit the commit message 9 # e, edit = use commit, but stop for amending 10 # s, squash = use commit, but meld into previous commit 11 # f, fixup = like "squash", but discard this commit's log message 12 # x, exec = run command (the rest of the line) using shell 13 # d, drop = remove commit 14 # 15 # These lines can be re-ordered; they are executed from top to bottom. 16 # 17 # If you remove a line here THAT COMMIT WILL BE LOST. 18 # 19 # However, if you remove everything, the rebase will be aborted. 20 # 21 # Note that empty commits are commented out
$ git status Changes not staged for commit: (use "git add/rm <file>..." to update what will be committed) (use "git checkout -- <file>..." to discard changes in working directory)
那么,对于已 add 进暂存区的文件,如何撤销本地修改?还是先使用 status 命令查看一下文件状态:
1 2 3 4 5
$ git status Changes to be committed: (use "git reset HEAD <file>..." to unstage)
modified: /there/is/a/modified/file
先取消暂存修改
Git 提示我们,可以使用 reset 命令取消暂存:
1
$ git reset /there/is/a/modified/file
取消暂存后,文件状态就回到了跟“例1”一样了:
1 2 3 4 5 6
$ git status Changes not staged for commit: (use "git add/rm <file>..." to update what will be committed) (use "git checkout -- <file>..." to discard changes in working directory)
modified: /there/is/a/modified/file
再撤销本地修改
这时按提示使用 checkout 即可:
1
$ git checkout -- /there/is/a/modified/file
这时工作目录就干净了:
1 2
$ git status nothing to commit, working directory clean
可以看到,结合使用 reset 和 checkout 命令,可以撤销 index 和 working tree 的修改。
一步到位
那么有更便捷的、一步到位的办法吗?有,指定提交即可:
1 2 3 4 5
$ git status Changes to be committed: (use "git reset HEAD <file>..." to unstage)
modified: /there/is/a/modified/file
1
$ git checkout HEAD -- /there/is/a/modified/file
1 2
$ git status nothing to commit, working directory clean
那么 checkout 命令的全貌究竟是怎样的呢?
checkout 命令格式
checkout 命令的格式及描述如下:
1 2 3
git checkout [<tree-ish>] [--] <paths>...
Updates the named paths in the working tree from the index file (default) or from a named <tree-ish> (most often a commit, tag or branch)
This form copy entries from <tree-ish> to the index for all <paths>. (It does not affect the working tree or the current branch.)
与 checkout 命令的参数一模一样,区别是什么?
命令
操作目标
描述
checkout
工作目录(working tree)
用于撤销本地修改
reset
暂存区(index)
只用于覆盖暂存区
因此 git reset <paths> 等于 git add <paths> 的逆向操作。
如果企图用 reset 命令覆盖工作目录,是会报错的:
1 2
$ git reset --hard /there/is/a/modified/file fatal: Cannot do hard reset with paths.
关系
After running git reset <paths> to update the index entry, you can use git checkout -- <paths> to check the contents out of the index to the working tree.
Alternatively, using git checkout [<tree-ish>] [--] <paths> and specifying a commit, you can copy the contents of a path out of a commit to the index and to the working tree in one go.