由于结合了开发中可能遇到的场景,篇幅较长,不过我以为颇有助于你理解 git 的运做机制,而不是死记硬背命令。linux
HEAD指针 始终指向的是当前分支的最新版本号,HEAD^, HEAD^^, ^ 的个数 n 或 HEAD~n,n 表明前 n 个版本号。git
在项目中直接使用 linux rm 只会删除工做区的文件,git rm 同在删除工做区文件的同时删除 stage 中的,或使用 git rm --cached 只删除 stage 中的。github
一些基本的操做fetch
#全局配置 git config --global user.name "your username" git config --global user.email youremail@email.com git config --global color.ui true # mkdir git_proj & cd git_proj git init echo "# readme.md" >> README.md git add README.md git commit -m "readme commit" # 添加远程仓库 并给它取个别名 origin git remote add origin git@github.com:username/repositoryName.git # 将本地仓库推送至 origin 的 master 分支并与此分支关联(-u 的做用,后期没必要在使用) git push -u origin master # 从远程仓库 origin 的 master 分支获取最新源码并下载到 tmp 分支 git fetch origin master:tmp # 比对 tmp 分支于 master 分支作了哪些改动 git diff master tmp # 合并 tmp 分支到 master 分支 git merge tmp # clone copy 一个完整的远端仓库到本地 git clone git@github.com:username/repositoryName.git # pull 获取 origin 的 master 分支并直接和当前分支合并 # 因此可能会发生冲突 git pull origin master
checkout 命令有两个主要做用:切换分支 和 回滚文件到当前的 stage 版本 或 repository 版本
一、切换分支ui
# 切换到 new_branch 分支 git checkout new_branch # 建立并切换到 new_branch 分支 git checkout -b new_branch
二、回滚工做区的文件到最新 stage 版本 或 repository 版本,即从 stage 或 repository 中检出最新版本spa
# -- 是文件标示符 表名后面的参数为文件 避免产生切换 branch 的歧义 git checkout -- <filename>
回滚时会先检查 stage 中是否有对应的文件,若是没有才会使用 repository 中最新的版本。而当对某文件进行了屡次修改和 add 操做后,使用 checkout 咱们只能将文件回滚到最新一次的 add 的版本。
但在某些场景下咱们可能想回滚到 repository 中的最新版本,怎么作呢?配合 reset 命令的能够很容易作到。
先给出命令:设计
git reset HEAD <filename> & git checkout -- <filename>
这样就能够将工做区的 filename 回滚到 repository 中的最新版本了。具体原理咱们将在实例中详细的讲解。指针
git 的 reset 命令比较绕,须要耐心的理解。简单来讲,reset 有三种重置级别,咱们须要准确理解每一个级别的做用。日志
soft:回退版本号。做用于 repositorycode
mixed:回退版本号,重置 stage。做用于 repository 和 stage
hard :回退版本号,重置 stage,重置工做区源码。做用于 repository,stage 和 workspace
咱们简单展现下 repository 的版本号,咱们以此为 demo 分别尝试三个级别的 reset
git log version D (HEAD) <-- HEAD指针 version C (HEAD^) version B (HEAD^^) version A (HEAD~3)
命令格式:
git reset [--soft|--mixed|--hard] version_no <filename>
--soft:只是单纯的移动 repository 的 HEAD指针 到制定版本号。stage 和工做区没有任何变化。
# 将 HEAD 指针回滚至上一版本 使用 git log 你会发现提交日志退回到了上一版本号 git reset --soft HEAD^ #版本号现状 version C <-- HEAD指针 version B version A
--mixed:默认选项,移动 repository 的 HEAD指针 到指定版本号,同时用此版本重置 stage 区,因此可能会让工做区的某些文件处于 unstage 状态(当工做区的文件与 repository 中的版本不一致时)。注意,这里是能够指定文件的。soft 自己和文件无关,hard 则是不能单独指定文件,只能所有重置。
# HEAD指针 仍是指向 HEAD git reset HEAD^2 <filename> #版本号现状 version B <-- HEAD指针 version A
HEAD指针 指向 version B,而且 stage 已经被 version B 的文件重置,工做区则不受影响。
这里有个很实用的小技巧:
git reset version_no <filename> & git checkout -- <filename>
这两个命令组合在一块儿可让工做区的指定文件回滚到 repository 中对应的 version_no 版本。
若是 version_no 是 HEAD 的话那就能够回滚文件到最新一次的提交。
--hard:谨慎使用!!!移动 repository 的 HEAD指针 到指定版本号,同时用此版本重置 stage 区 和 工做区源码。这里要特别注意,工做区的源码也会被覆盖重置掉,你的修改会所有丢失。简单来讲就是将代码完全恢复到指定版本。hard 是没办法指定文件的,要么回滚,要么全回滚。
# HEAD指针 仍是指向 HEAD git reset --hard HEAD^3 #版本号现状 version A <-- HEAD指针
此时,HEAD指针 指向 version A,而且 stage 和 工做区的文件已经被 version A 的文件重置。整个项目的状态彻底回到提交 version A 时按下回车键的那一刻。
git rm 不一样于直接使用 rm,git rm 会删除工做区 和 stage 区的内容。注意:这里你没办法再使用 git checkout -- <filename> 来回滚操做了,由于工做区也没有 filename 文件了,没办法与 repository 作关联,只能使用 git reset HEAD <filename> 来重置 stage 中的此文件,而后 git checkout -- <filename>
git rm [--cached] [-r] [-f] <filename>
这里就提示一点,只想把 stage 中的文件删除掉让文件脱离 git 的管理,可使用
git rm --cached <filename>
此时工做区的 filename 并不会被删除,但状态会被改成 untracked,同时 stage 会记录下 filename 的状态为删除,提交的话版本库将新增一个 filename 被删除掉的版本。
删除 stage 中的文件和使用 reset命令 重置 stage 中的文件是有区别的,删除会让文件状态更改成 untracked,而重置会让文件状态更改成 unstage(若是工做区和 stage 文件内容不一致)。
小实例场景:
一、回滚工做区某文件到指定的 repository 版本
工做中,咱们可能会针对某文件作屡次修改和 add 到 stage 的操做,然后发现思路彻底错了,须要从新设计开发。
好比文件 foo 的 A版 我提交了一次后,又进行了 B版 和 C版 的两次修改并 add 到了 stage 区。第三次修改后 D版 我发现一开始思路就错了,须要从新设计。那此时直接使用 git checkout -- foo 是拿不到最初的 A版 的,由于 stage 区还存放着 foo 的 C版。此时咱们即可以使用 git reset HEAD foo 命令,repository 最新版本号中存放着 foo 的 A版,命令会在不移动 HEAD 的前提下,使用 foo A版 去重置 stage 区。命令执行后 stage 区的 foo 文件已是 A版 了。咱们再使用 git checkout -- foo 即可以将工做区的 foo D版 回滚至 A 版。即:
git reset HEAD foo & git checkout -- foo
HEAD 表明当前版本,因此 HEAD指针 不会移动。同时 stage 区会被 repository 的当前版本的 filename 重置,也就说 stage 区 存放的 filename 与 repository 中相同了。此时咱们再使用 git checkout -- <filename> 即可以回滚工做区的 filename 到 repository 的当前版本。其实就是利用 reset --mixed 会重置 stage 区,而后 checkout 会将 stage 区的文件检出到工做目录。固然,reset 很灵活,能够回滚任意指定的版本。
其实若是只是回滚至当前版本的话,还有个命令能实现相同的功能
git rm --cached <filename> & git checkout -- <filename>
git rm --cached <filename> 会将 stage 中的此文件删除,文件状态会变为 untracked,而后 checkout 时发现 stage 中木有此文件,故会去 repository 的当前版本中检出此文件。
git diff -- <filename> 工做区 比较 暂存区
git diff --cached -- <filename> 暂存区 比较 本地库当前版本
git diff HEAD~N -- <filename> 工做区 比较 本地库第N个版本
git diff HEAD HEAD^ -- <filename> HEAD 比较 HEAD^
git diff master tmp -- <filename> master 比较 tmp
git diff SHA1 SHA2 -- <filename> 比较两个历史版本之间的差别
还没结束...未完成...待更新....