目录
Git和SVN的区别
Git的安装
Git结构
Git和代码托管中心
本地库和远程库的交互
Git的命令行操作
本地库初始化
Git的基本操作
Git的分支
分支的操作
Git操作远程库(以GitHub为例)(团队内部协作)
GitHub跨团队协作
SSH免密登陆
IDEA配置Git
首先说说Git和SVN最大的区别,个人感觉最大的区别就是SVN必须要联网,SVN属于集中式版本控制,如果你不联网SVN就用不了了;但是Git本地就可以保存我完整的操作历史,很多操作在本地就可以完成。Git还有一个好处是可以保证文件的完整性,比如我从Git库中pull文件,就可以根据hash验证文件是否完整。
进入官网进行下载(https://git-scm.com/download/win):
下一步即可:
文件编辑器建议与Linux保持一致使用vim:
第一个的意思是不会修改环境变量,但是我们就只能在Git Bash中使用Git命令(最安全的选择);第二个的意思是会修改PATH环境变量,这样就可以在Windows窗口使用Git命令了(理论上是安全的,有点风险);第三个尽量不要用。这里使用第一个:
这里建议使用第一个。SSL比较通用。
关于换行符的转换方式,使用默认值即可:
使用Git Bash默认终端:
直接下一步:
等待安装即可:
finish:
安装完成后点击鼠标右键:
点击Git Bash Here能够打开终端:
Git主要分为工作区、暂存区、本地库:
工作区就是我们平时写代码的地方;暂存区是打算要提交但是还没有提交的区域,就将来可以提交到本地库也可以提交到远程库;本地库是实实在在存储历史版本的区域。
其实我们常用的GitHub就是一个Git的托管中心,还有GitLab也是。代码托管中心主要是用来维护远程库。
交互方式主要分为两种,团队内部协作和跨团队协作。
团队内部协作:
跨团队协作:
命令:git init
进入Git Bash:
接下来就可以使用Linux命令进行操作了。在H盘下新增一个Git的本地库gitDemo:
进入gitDemo,执行git init初始化本地库
在Linux系统中.开头的文件是隐藏文件,可以使用ll -a查看:
.git里面还有不少文件:
注意:.git 目录中存放的是本地库相关的子目录和文件,不要删除,也不要胡乱修改。
设置签名
主要用来区分开发人员身份。
形式:
用户名:Dongguabai
Email地址:[email protected]
辨析
这里设置的签名和登录远程库(代码托管中心)的账号、密码没有任何关
系。
项目级别/仓库级别:仅在当前本地库范围内有效。
命令:
git config user.name dongguabai1
git config user.email [email protected]
信息保存位置:./.git/config 文件
系统用户级别:登录当前操作系统的用户范围。
命令:
git config --global user.name dongguabai2
git config --global user.email [email protected]
信息保存位置:~/.gitconfig 文件
级别优先级:就近原则:项目级别优先于系统用户级别,二者都有时采用项目级别的签名;如果只有系统用户级别的签名,就以系统用户级别的签名为准;二者都没有不允许。
查看工作区状态 git status
将工作区的“新建/修改”添加到暂存区 git add [file name]
将暂存区的内容提交到本地库 git commit -m "commit message" [file name]
(如果是 commit 全部,直接 git commit -m "commit message" 不添加文件名即可)
查看历史纪录 git log、git reflog(可以显示回退版本需要移动的次数)
多屏显示控制方式:
空格向下翻页
b 向上翻页
q 退出--pretty=oneline 或者--oneline 每条日志只显示一行
版本进行前进或者回退
基于索引值操作 git reset --hard 索引值
使用^符号,只能后退 git reset --hard HEAD^ (注:一个^表示后退一步,n 个表示后退 n 步)
使用~符号,只能后退 git reset --hard HEAD~n (注:表示后退 n 步)
reset命令的参数对比:--soft(仅仅在本地库移动 HEAD 指针,不会修改本地文件)、--mixed(在本地库移动 HEAD 指针,重置暂存区,不会修改本地文件)、--hard(在本地库移动 HEAD 指针,重置暂存区,重置工作区,不会修改本地文件)
删除文件并找回(删除前,文件存在时的状态提交到了本地库)
git reset --hard [指针位置]
删除操作已经提交到本地库:指针位置指向历史记录
删除操作尚未提交到本地库:指针位置使用 HEAD
文件比较
git diff [文件名] 将工作区中的文件和暂存区进行比较
git diff [本地库中历史版本] [文件名] 将工作区中的文件和本地库历史记录比较
不带文件名比较多个文件
执行git status命令:
Dongguabai@LAPTOP-9SC9JSAA MINGW64 /h/gitDemo1 (master)
$ git status
On branch master //代表现在在master分支上
No commits yet //本地库中现在还没有任何的已经提交的
nothing to commit (create/copy files and use "git add" to track) //没有什么可提交的(暂存区里面是空的)
创建一个文件test,文件内容为aaaa:
再用git status看下:
Dongguabai@LAPTOP-9SC9JSAA MINGW64 /h/gitDemo1 (master)
$ git status
On branch master //在master分支
No commits yet //本地库没有已经提交的内容
Untracked files: //没有被追踪的文件
(use "git add ..." to include in what will be committed) //提示可以使用git add命令
test //文件会高亮红色显示
nothing added to commit but untracked files present (use "git add" to track) //暂存区没有什么可提价的,但是有未追踪的文件存在(可以使用git add命令去追踪)
使用git add命令:
Dongguabai@LAPTOP-9SC9JSAA MINGW64 /h/gitDemo1 (master)
$ git add test
warning: LF will be replaced by CRLF in test. //在test文件中LF将会被替换为CRLF文件,这里与我们安装的时候选择换行符格式的时候相关
The file will have its original line endings in your working directory //在工作目录中任然会保存你的原始文件
再用git status看下状态:
//在master分支上
//本地库还是没有已经提交的
//新建文件test将要被提交(可以使用git rm --cached
使用git commit从暂存区提交到本地库,要注意首先必须要git add:
中间会进入让你输入提交信息的界面:
Dongguabai@LAPTOP-9SC9JSAA MINGW64 /h/gitDemo1 (master)
$ git commit test
warning: LF will be replaced by CRLF in test.
The file will have its original line endings in your working directory
[master (root-commit) 2b8f514] my first git commit
1 file changed, 1 insertion(+) //一行被增加的
create mode 100644 test
commot完成后再git status:
修改一下test文件,再查看git status:
这时候会显示当前test文件被修改了。
最后一行的提示是可以使用git add + git commit命令去提交或者直接使用git commit命令去提交(这与新建文件不一样,新建文件这里的提示是必须要git add)。
查看历史记录,执行git log:
Dongguabai@LAPTOP-9SC9JSAA MINGW64 /h/gitDemo1 (master)
$ git log
commit 20aa01bf043a9fa2c3953c2845529e9f2b128de0 (HEAD -> master)
Author: dongguabai1
Date: Mon Nov 12 18:52:16 2018 +0800
my 4th commit
commit 15940dbd54460bdb921fd94fa2ee707b4b83d13a
Author: dongguabai1
Date: Mon Nov 12 18:47:58 2018 +0800
my third commit
commit 27a55aed2cd05826595bf40b9272fa13fc98bfff
Author: dongguabai1
Date: Mon Nov 12 18:19:33 2018 +0800
my second change
为了方便演示具体效果,这里多git commit几次test文件。再执行git log:
可以看到最下面出现了光标和冒号,这是因为log太多,一屏放不下了。 可以使用空格向下翻页,b向上翻页,q退出。由于日志太多不方便查看可以使用--pretty=oneline 或者--oneline每条日志只显示一行:
使用git -reflog可以方便的进行历史纪录的回退和前进:
接下来操作版本的前进或者回退,回退到索引值为f2d8e6b:
最后会显示这个版本的日志信息。
再执行git reflog:
接下来测试删除操作,先新建一个文件testDelete.txt。
前面已经提到过了,删除时,文件存在的状态要已经提交到了本地库,但是我们这个是新建的文件,必须要先git add,再git commit:
删除testDelete.txt文件:
查看状态:
有提示说明可以使用git add/rm
再进行提交操作:
使用git reflog查看一下版本记录:
当前的版本是删除了testDelete.txt文件后的版本,如果我们回退到删除前的版本,那么testDelete.txt文件还是存在的:
接下来再演示另一种情况,我们删除文件提交到暂存区了,但是还没有提交到本地库。先新建文件vim abc.txt。
执行git add、git commit:
删除文件abc.txt,提交到本地库但不提交到暂存区:
再来测试文件比较,使用diff命令。
先新建两个文件a.txt,b.txt。
a.txt内容为:
现在修改一下a.txt:
接下来使用git diff [文件名]命令比较a.txt文件:
红色减号代表是删掉的行,绿色加号代表是新增的行。
接下来将a.xtx添加到暂存区,再进行diff比较:
会发现没有内容。也就是说git diff如果没有别的参数,那就是与暂存区进行比较,现在加上版本进行比较:
又能够看到差异了。
如果git diff不带文件名就能够比较所有的文件。
什么是分支
在版本控制过程中,使用多条线同时推进多个任务。
在版本库初始化完毕后,就会有一个master(主干)分支。没开发完之前不想影响mater分支,就会创建一个新的分支feature_blue,在新的分支里面开发。新的分支就是从master中复制过来的,此时feature_blue的内容和master的内容是一样的。同理,可以再创建分支。分支在彼此开发的过程中是彼此独立的。分支开发失败直接删除就行了,一些比较复杂的业务还会创建分支进行测试。
开发完毕就会合并分支到master,此时对于master就是一个版本的升级。
一般对master的测试会创建一个hot_fix分支,进行测试热修复BUG,BUG修复完再合并至master:
分支的好处
可以同时并行推进多个功能开发,提高开发效率;各个分支在开发过程中,如果某一个分支开发失败,不会对其他分支有任
何影响。失败的分支删除重新开始即可。
创建分支 git branch [分支名]
查看分支 git branch -v
切换分支 git checkout [分支名]
合并分支:
第一步:切换到接受修改的分支(被合并,增加新内容)上,即git checkout [被合并分支名]
第二步:执行 merge 命令,git merge [有新内容分支名]
解决合并分支冲突:
冲突表现:
解决冲突:
第一步:编辑文件,删除特殊符号
第二步:把文件修改到满意的程度,保存退出
第三步:git add [文件名]
第四步:git commit -m "日志信息"
注意:此时 commit 一定不能带具体文件名
首先执行git status看看:
显示当前就在master分支上。从目录最后的提示也能看出当前再master分支上。
查看分支:
创建一个hot_fix分支:
现在就有两个分支了。切换分支:
有了分支之后就可以在分支中进行不同的操作。现在对文件进行相关的操作:
然后add、commit:
在刚创建hot_fix分支的时候,hot_fix分支和master分支的内容是一致的,版本进度也是一致的,但是在hot_fix分支中修改了test文件之后hot_fix分支有了新的修改:
如果这时候要让hot_fix分支的内容与master分支的内容一致就需要合并分支。
合并分支
第一步:切换到接受修改的分支上,这里是master分支:
第二步:在master分支上执行merge命令:
再看master分支上的test文件内容已经跟hot_fix分支中的test文件一样了:
解决分支合并后的冲突问题
数据准备:
接下来在master上合并hot_fix:
可以看到,显示出自动合并已经失败了。需要手动合并了,也能够看出现在处于合并的状态:
可以查看产生冲突的test文件,会发现文件中已经有了一些特殊的标记:
接下来解决冲突,先将特殊符号内容删除,然后修改文件内容:
保存退出后,可以看看git的状态:
然后git add test再git status看看:
显示所有的冲突已经合并了,可以git commit结束合并,要注意的是这里的git commit不能带文件名:
能够发现分支也已经切换回master了。
git remote -v 查看当前所有远程地址别名
git remote add [别名] [远程地址] 创建远程库地址别名
git push [别名] [分支名] 推送
git origin [远程地址] 克隆(git clone)
完整的把远程库下载到本地
创建 origin 远程地址别名
初始化本地库pull=fetch+merge 拉取操作
git fetch [远程库地址别名] [远程分支名] (可以先查看远程库的内容,避免直接修改本地库)
git merge [远程库地址别名/远程分支名]
git pull [远程库地址别名] [远程分支名] (相当于fetch+merge)fetch和pull都是读操作,不需要验证身份
解决协同开发冲突
如果不是基于 GitHub 远程库的最新版所做的修改,不能推送,必须先拉取。
拉取下来后如果进入冲突状态,则按照“分支冲突解决”操作解决即可。第一步:git pull [远程库地址别名] [远程分支名] ,进入解决冲突的状态
第二部:删除特殊符号,修改代码,重新add、commit(注意解决冲突的时候commit不需要文件名)、push
本地库和远程库交互的过程:
先创建并初始化一个本地库:
创建一个文件a.txt,并提交到本地库:
接下来创建远程库。进行GitHub创建一个新的Repository:
创建了远程库后下一步需要把本地库的内容上传到远程库。首先需要知道远程库的地址:
先查看当前所有的远程地址的别名:
将刚才创建的远程库的地址添加到git中并取别名:
fetch表示这个地址用来拉回,push表示这个地址用来推送。
将本地库分支推送至远程库:
账号密码输入后:
也可以看出从本地的master到了远程的master,因为远程库之前是没有这个分支的,这个对于远程库来说是一个新建的分支。
这时候在远程库中就能看到了:
这时候如果需要其他人协同开发,可以让其他人在本地执行克隆操作,这里在githubTest2中模拟其他人的操作:
可以查看本地的内容中已经有了远程库的内容:
同时也有.git目录,有了这个目录我们就不需要再在本地初始化了:
再git remote -v看看远程库的别名,发现也已经创建好了:
接下来模拟他人在本地库进行修改,然后提交到本地库:
这时候如果协同开发者想push到远程库,现在是不可以的:
需要邀请其他开发者首先加入团队,进入GitHub:
可以复制相关的邀请链接发送给协同开发者,当然也会有邮件发送:
接受以后就是团队成员了,就有写的权限了。
再执行push就会成功了。
多说一点,Windows有凭据管理器会自动记住密码:
再进入之前的本地库:
内容已经与由其他开发者提交后的内容不一样了:
抓取远程库的内容:
查看a.txt:
发现本地库的内容并没有变化。因为fetch只是将远程库的文件下载到本地,想看fetch下来的内容,可以先切换到testOrigin/master:
再切换回去:
这时候可以再进行合并:
接下来演示一下解决协同开发中的冲突问题。如果两个开发者都修改了同一个文件,只有先推送的那个开发人员才能够push上去,后推送的开发人员就push不上去了,必须先拉去下来才能够取推送。
先用Dongguabaiwuyu修改a.txt并push:
查看远程库的内容:
在使用Dongguabaiwuyu22修改a.txt并push,发现已经有冲突了:
先执行git pull [远程库地址别名] [远程分支名]进入解决冲突的状态:
看看冲突文件:
解决冲突后add、commit、push:
查看远程库的内容:
跨团队协作其实就是把别人团队的远程库Fork到自己的远程库,后面的就跟操作自己的远程库一样了。修改完成后发起一个pull request给原团队,原团队审核后merge即可。
让Dongguabaiwuyu22 ForkDonggauabaiwuyu中的远程库:
对于Dongguabaiwuyu22来说,就是操作自己的远程库。就是clone自己的远程库到本地库,再进行相应的操作,有修改或者增加执行add、commit、push等操作,这里就不多说了。
将Fork的项目修改后提交到自己的远程库后进行Pull request操作:
然后需要发消息给Dongguabaiwuyu:
然后再登陆Dongguabaiwuyu的Github,能看到有一个Pull request:
还可以进行对话:
再进入Dongguabaiwuyu22的GitHub可以看到对话:
如果没问题,可以选择合并:
合并后内容已经更新:
最后就是既然远程库修改了,pull到本地即可。
进入当前用户的家目录
$ cd ~
删除.ssh 目录
$ rm -rf .ssh
运行命令生成.ssh 密钥目录
$ ssh-keygen -t rsa -C [email protected]
[ 注意:这里-C 这个参数是大写的 C]
进入.ssh 目录查看文件列表
$ cd .ssh
$ ls
查看 id_rsa.pub 文件内容并复制
之前在克隆项目地址的时候,有一个Https的,还有一个SSH的:
这样就可以避免每次都需要输入用户名密码(虽然Windows 7以上的系统已经解决了这个)。
进入家目录:
删除.ssh目录:
运行命令生成.ssh 密钥目录(连续三个回车):
进入.ssh:
这时候可以添加SSH地址到本地库中:
这时候操作push就不需要再输入用户名和密码了。
下载gitignore插件:setting->plugins->Browse repositories,搜索.gitignore插件并下载:
也可以右键文件将其加入忽略的名单中:
然后就会发现被忽略的文件名变成了灰色。
.gitignore只能忽略那些原来没有被track的文件,如果某些文件已经被纳入了版本管理中,则修改.gitignore是无效的。那么解决方法就是先把本地缓存删除(改变成未track状态),然后再提交:
输入:
git rm -r --cached filePath
git commit -m “remove xx”
或者:
git rm -r --cached .
git add .
git commit -m “update .gitignore”
来解释下几个参数 -r 是删除文件夹及其子目录 –cached 是删除暂存区里的文件而不删除工作区里的文件,第一种是删除某个文件,第二种方法就把所有暂存区里的文件删了,再加一遍,相当于更新了一遍。(具体可参看https://blog.csdn.net/Dongguabai/article/details/84074087)
此时在commit时依然有test:
但是在.gitignore中已经加入了test/java:
这是因为之前已经将test/java add到了缓存区,现在将test/java从缓存区中删除:
再commit的时候已经看不到test了:
现在在test中新家一个类,看能否被忽略(都是灰色的):
提交时依然不会出现test中的内容:
配置Git:进入File-->Setting->Version Control-->Git:
设置Github:进入File-->Setting->Version Control-->GibHub:
创建本地仓库,VCS-->Import into Version Control:
选择项目所在位置:
此时项目文件全为红色,项目选中,右键add,项目全部变成绿色,此时文件只是处于暂存区,并没有真正进入到版本库中:
点击commit,此时项目文件从暂存区真正进入版本库中,项目文件变成黑色:
将项目提交到GitHub:
在GitHub上创建一个Repository:
在idea中git push:
进入GitHub可以查看到相应的工程:
下面来模拟别人提交,然后更新,为了方便,直接在GitHub上进行修改:
在idea上先fetch,再切换分支后先进行比较,最后merge即可,这样可以实现类型Eclipse SVN“与资源库同步”功能(具体可参看:https://blog.csdn.net/Dongguabai/article/details/84075067)。
参考资料:
https://www.cnblogs.com/whitle/p/8874769.html
https://www.cnblogs.com/hkgov/p/7694101.html
https://blog.csdn.net/qq_34590097/article/details/56284935