1. 三种git diff的区别:
git diff readme.txt 是工作区和暂存区的对比
git diff – cached readme.txt 是暂存区和分支的对比
git diff HEAD – readme.txt 工作区和分支的对比
用git diff命令查看不同(以下指的是一个单一文件在整个创建过程中的状态,对于其他不同的文件状态,其实只要知道文件工作区-缓存区-分支的区别以及git add和git commit的区别,容易分析出来,比如对于一个文件修改了一次,然后git add,然后又修改一次,当前三种git diff查看,显示的不同是什么样的?)。
- 1.新建一个文件
1.新建一个文件之后,没有add以及commit之前,三者都看不到区别,因为该文件还未到缓存区也未到版本库。
2.add后,没有commit之前,git diff --cached *和git diff HEAD --看到区别。
3.commit之后,三者都没反应。(*代表文件名)
- 2.修改一个已经存在的文件
1.修改后,没有add以及commit之前,git diff *与 git diff HEAD – *看到区别,git diff --cached *没反应。
2.add后,没有commit之前,git diff --cached *与 git diff HEAD – * 看到区别,git diff * 没反应。
3.commit之后,三者都没反应。(*代表文件名)
工作区:电脑里能看到的目录,比如我的learngit文件夹就是一个工作区
工作区有一个隐藏目录.git,这个不算工作区,而是Git的版本库。
Git的版本库里存了很多东西,其中最重要的就是称为stage(或者叫index)的暂存区,还有Git为我们自动创建的第一个分支master,以及指向master的一个指针叫HEAD
第一步是用git add把文件添加进去,实际上就是把文件修改添加到暂存区;
第二步是用git commit提交更改,实际上就是把暂存区的所有内容提交到当前分支。
因为我们创建Git版本库时,Git自动为我们创建了唯一一个master分支,所以,现在,git commit就是往master分支上提交更改。
你可以简单理解为,需要提交的文件修改通通放到暂存区,然后,一次性提交暂存区的所有修改。
2.git status
用于查看在工作区的文件的状态(以下指的是一个单一文件在整个创建过程中的状态,对于其他不同的文件状态,其实只要知道文件工作区-缓存区-分支的区别以及git add和git commit的区别,容易分析出来)。
1,新创建的文件,还没git add:
2.新创建的文件,已经git add,还未git commit
3.新创建的文件已经git commit了
1.修改以前的文件,刚修改之后,还没git add:
2.修改以前的文件,刚修改之后,git add了,但还没git commit:
3.文件已经git add和git commit了
3.版本回退
git reset --hard HEAD^ (一个^代表回到当前HEAD的上一个版本,几个 ^代表回到当前HEAD的上几个版本 )
git reset --hard id(id代表要回退到的版本号)
穿梭前,用git log可以查看提交历史(commit历史),以便确定要回退到哪个版本(如果嫌输出信息太多,看得眼花缭乱的,可以试试加上–pretty=oneline参数)。
如果命令行窗口关闭了,要重返未来,用git reflog查看命令历史(所有输入命令的历史),以便确定要回到未来的哪个版本。
在英文模式下按一下q,退出git log以及git reflog状态。
4. 时光机穿梭
4-1.管理修改
- 必须是使用git add到暂存区的修改记录才会被git commit命令提交。
1.比如存在一个文件,修改了第一次,然后git add到暂存区,然后修改第二次,之后就git commit。那么其实第二次的修改记录并没有被commit(因为commit只负责把暂存区的修改提交,而第二次的修改并没有放到暂存区里面),接下来如果再次git add(就是把第二次的修改放到暂存区),然后再git commit,那么第二次的修改也被记录下来了。
2.比如存在一个文件,修改了第一次,之后没有git add,然后又修改了第二次,然后git add,git commit。和上一种情况不同之处在于,因为前两次提交之间并没有git add,所以其实就是相当于一次修改然后进行了git add和git commit。
4-2.撤销修改
场景1:当你改乱了工作区某个文件的内容,还未添加到暂存区时,想直接丢弃工作区的修改时,用命令git checkout – filename(说是丢弃修改,其实就是把版本库中当前最新内容覆盖到工作区中。当然也可以手动在文件中把修改了的内容再改回来,不过,如果你改动太多,那不一定还都能记得,而这个命令,可以直接帮你丢弃所有修改)。
场景2:当你不但改乱了工作区某个文件的内容,还添加到了暂存区(git add)时,想丢弃修改,分两步,第一步用命令git reset HEAD ,就回到了场景1,第二步按场景1操作。
git reset HEAD
该操作 可以 拉取最近一次提交到版本库的文件到暂存区 并且该操作不影响工作区
简单的来说 就是可以帮我们从版本库中 拉取文件到 暂存区 当我们把工作区的某个文件弄乱了 我们就可以使用该命令 把版本库中的那个文件拉到暂存区 然后在拉回工作区
场景3:已经提交了不合适的修改到版本库时,想要撤销本次提交,参考版本回退一节,不过前提是没有推送到远程库。
4-3.删除文件
- 用rm filename删除工作区中的文件(或者自己手动删除),只是工作区中删除了,并不是真正的删除了
- 1.想真正删除一个文件。不仅仅是工作区删除了文件,版本库中的也想删除,那就使用git rm filename 然后再git commit。所以正常操作有两种:1:rm filename+git rm filename+git commit 2.git rm+git commit
注意:rm filename+git commit(虽然文件也能被删除,但是这个删除记录并不会被提交) - 2.误删了文件。不过因为版本库里还有呢,所以可以很轻松地把误删的文件恢复到最新版本:
git checkout – filename
命令git rm用于删除一个文件。如果一个文件已经被提交到版本库,那么你永远不用担心误删,但是要小心,你只能恢复文件到最新版本,你会丢失最近一次提交后你修改的内容。
5.远程仓库
5-1.添加远程库
要关联一个远程库,本地新建一个文件夹,进入该文件夹,然后使用命令git remote add origin git@server-name:path/repo-name.git
关联后,使用命令git push -u origin master 第一次
推送master分支的所有内容;
此后,每次本地提交后,只要有必要,就可以使用命令git push origin master推送最新修改;
分布式版本系统的最大好处之一是在本地工作完全不需要考虑远程库的存在,也就是有没有联网都可以正常工作,而SVN在没有联网的时候是拒绝干活的!当有网络的时候,再把本地提交推送一下就完成了同步,真是太方便了!
5-2.从远程库克隆
要克隆一个仓库,首先必须知道仓库的地址,然后使用git clone命令克隆。
例如:git clone git@github.com:xytywh/learngit.git
Git支持多种协议,包括https,但通过ssh支持的原生git协议速度最快。
6.分支管理
6-1.创建与合并分支
查看分支:git branch
创建分支:git branch
切换分支:git checkout 或者git switch
创建+切换分支:git checkout -b 或者git switch -c
合并某分支(name分支)到当前分支:git merge
删除分支(已经合并过的分支):git branch -d
参考:git 切换分支时会把未add或未commit的内容带过去
6-2.解决冲突
当Git无法自动合并分支时,就必须首先解决冲突。解决冲突后,再(add+commit)提交,合并完成。
解决冲突就是把Git合并失败的文件手动编辑为我们希望的内容,再(add+commit)提交。
用git log --graph命令可以看到分支合并图。
6-3.分支管理策略
合并分支时,加上–no-ff参数就可以用普通模式合并,合并后的历史有分支,能看出来曾经做过合并,而fast forward合并就看不出来曾经做过合并。
6-4 Bug分支
修复bug时,我们会通过创建新的bug分支进行修复,然后合并,最后删除;
当手头工作没有完成时,先把工作现场git stash一下,然后去修复bug,修复后,再git stash pop,回到工作现场;
在master分支上修复的bug,想要合并到当前dev分支,可以用git cherry-pick 命令,把bug提交的修改“复制”到当前分支,避免重复劳动
总的来说,就是,在分支下进行的工作,如果不commit的话,回到master,就会显示出你在分支下你添加的工作。这个时候,你在master下修改完bug提交后,正在分支进行的工作也会提交了。为了避免这个情况,你就在分支下,git stash将工作隐藏,这个时候,切换到master时候,修改了bug,提交。分支的内容不会被提交上去。
实际上,如果在一个分支中进行更改后,却没有add和commit,切换到master是不安全的(或者说是不允许的,直接报错)。所以当目前分支中的工作没有完成,就想切换到其他分支处理bug,就必须使用stash。
6-5.Feature分支
如果要丢弃一个没有被合并过的分支,可以通过git branch -D 强行删除。
6-6.多人协作
因此,多人协作的工作模式通常是这样:
-
1.首先,可以试图用git push origin 推送自己的修改;
-
2.如果推送失败,则因为远程分支比你的本地更新,需要先用git pull试图合并;
-
3.如果合并有冲突,则解决冲突,并在本地提交;
-
4.没有冲突或者解决掉冲突后,再用git push origin 推送就能成功!
如果git pull提示no tracking information,则说明本地分支和远程分支的链接关系没有创建,用命令git branch --set-upstream-to origin/。
这就是多人协作的工作模式,一旦熟悉了,就非常简单。
- 总结
查看远程库信息,使用git remote -v;
本地新建的分支如果不推送到远程,对其他人就是不可见的;
从本地推送分支,使用git push origin branch-name,如果推送失败,先用git pull抓取远程的新提交;
在本地创建和远程分支对应的分支,使用git checkout -b branch-name origin/branch-name,本地和远程分支的名称最好一致;
建立本地分支和远程分支的关联,使用git branch --set-upstream branch-name origin/branch-name;
从远程抓取分支,使用git pull,如果有冲突,要先处理冲突。
6-7.Rebase
rebase操作可以把本地未push的分叉提交历史整理成直线;
rebase的目的是使得我们在查看历史提交的变化时更容易,因为分叉的提交需要三方对比。
7.标签管理
标签就是一个commit号的别名,便于记忆,类似于IP地址和网址的关系。
7-1 创建标签
命令git tag 用于新建一个标签,默认为HEAD,也可以指定一个commit id;
命令git tag -a -m "blablabla…"可以指定标签信息;
命令git tag可以查看所有标签。
7-2 操作标签
命令git push origin 可以推送一个本地标签;
命令git push origin --tags可以推送全部未推送过的本地标签;
命令git tag -d 可以删除一个本地标签;
命令git push origin :refs/tags/可以删除一个远程标签。
8.自定义git
8-1 忽略特殊文件
忽略某些文件时,需要编写.gitignore;
.gitignore文件本身要放到版本库里,并且可以对.gitignore做版本管理!
参考:廖雪峰官网Git教程
学习git的总结