1. Git介绍
Git是目前世界上最先进的分布式版本控制系统。Git 不仅仅是个版本控制系统,它也是个内容管理系统(Software configuration management ,SCM),工作管理系统等。
git远程操作管理
git使用规范流程
2. SVN与Git的区别
git和使用SVN一样,需要服务端和客户端,是一种Client-Server(C/S)结构。
Git 与 SVN 区别点:
1、Git 是分布式的,SVN 不是:这是 Git 和其它非分布式的版本控制系统。
2、Git 把内容按元数据方式存储,而 SVN 是按文件:将所有的资源控制系统都是把文件的元信息隐藏在一个类似 .svn、.cvs 等的文件夹里。
3、Git 的内容完整性要优于 SVN:Git 的内容存储使用的是 SHA-1 哈希算法。这能确保代码内容的完整性,确保在遇到磁盘故障和网络问题时降低对版本库的破坏。
SVN是集中式版本控制系统,版本库是集中放在中央服务器的,开发的时候,用的都是自己的电脑,所以首先要从中央服务器那里得到最新的版本,需要把自己做完的代码推送到中央服务器。
Git是分布式版本控制系统,它就没有中央服务器的,同一个Git仓库,可以分布到不同的机器上。每个人的电脑就是一个完整的版本库,都是在自己的电脑上。也就是每个人的电脑都有一个完整的版本库。
每个人的电脑都有一个完整的版本库,那多个人应该如何协作呢?
比如说自己在电脑上改了文件A,其他人也在电脑上改了文件A,这时,然后都把修改提交推送到服务器仓库里,也从服务器仓库中拉取别人的提交。这样你们两之间就可以互相看到对方的修改了。
3. windows上安装使用Git
3.1 客户端msysgit
github是服务端,在自己电脑上使用git我们还需要一个git客户端,git客户端有很多,da选用msysgit,这个只是提供了git的核心功能,而且是基于命令行的。如果想要图形界面的话需要在msysgit的基础上安装TortoiseGit。
git和使用SVN一样,需要服务端和客户端,是一种Client-Server(C/S)结构。安装SVN服务,然后使用使用SVN需要安装TortoiseSVN客户端才能使用。
3.1.1 下载安装msysgit
常用的GitHub客户端msysgit,也就是git-for-windows。
官网
https://git-for-windows.github.io/
https://gitforwindows.org/
我下载了最新版64位:Git-2.19.0-64-bit.exe
安装,一路Next就好了,根据提示作相应改变。
弹出来框框输入查看版本 git --version
这就算安装成功了。
因为Git是分布式版本控制系统,所以需要填写用户名和邮箱作为一个标识。
配置Git
$ git config --global user.name "luolei"
$ git config --global user.email "172***80@qq.com"
说明:git config --global,有了这个参数,表示你这台机器上所有的Git仓库都会使用这个配置。
3.2 创建一个版本库测试
版本库又名仓库 repository,可以简单的理解一个目录,这个目录里面的所有文件都被Git管理起来,每个文件的增删改,Git都能记录控制,以便在将来某个时刻还可以将文件”还原”。
3.2.1 创建一个版本库
在F盘创建文件夹lxgit,进入文件夹,接着初始化仓库,就可看到在lxgit目录下创建了一个.git隐藏目录,这就是版本库目录。
$ cd /f
$ mkdir lxgit #创建仓库
$ cd /f/lxgit/ #进入文件夹
$ git init #始化仓库
$ ls -al #查看文件,包括隐藏的
3.2.2 把文件添加到版本库中
(1)在lxgit目录下创建一个文件lx_code.txt并给予内容。
$ touch lx_code.txt
$ vim lx_code.txt
$ cat lx_code.txt
111
222
333
(2)使用命令 git add filename 将文件添加到暂存区里面去。
用命令 git commit 把文件提交到仓库。
报错了:
warning: LF will be replaced by CRLF in lx_code.txt.
The file will have its original line endings in your working directory
警告:lx中的LF将替换为CRLF_代码.txt.文件的原始行尾将位于工作目录中。
解决:core.autocrlf=false
https://www.jianshu.com/p/450cd21b36a4
LUOLEI@DESKTOP-SBABRDF MINGW64 /f/lxgit (master)
$ git add lx_code.txt
LUOLEI@DESKTOP-SBABRDF MINGW64 /f/lxgit (master)
$ git commit -m 'version1 初次提交'
[master (root-commit) 417cd62] version1 初次提交
1 file changed, 3 insertions(+)
create mode 100644 lx_code.txt
LUOLEI@DESKTOP-SBABRDF MINGW64 /f/lxgit (master)
$ git log
commit 417cd6211d7a446e677bcc6eef10aed0597eda30 (HEAD -> master)
Author: luolei <1726420180@qq.com>
Date: Sun Jun 28 19:52:31 2020 +0800
version1 初次提交
(3)查看版本记录:
$ git log
commit后面是版本号
HEAD 是当前最新版本
(4)来查看是否还有文件未提交
git status
(5)编辑lx_code.txt,修改内容,来查看是否还有文件未提交
添加一行
444
发现还有没提交的。
我想知道这个文件到底改了什么,怎么做?
$ git diff lx_code.txt
确定修改的内容后,就可以提交commit了。
我只在原有内容上添加了一行444,他检测我添加了两行。不影响,继续。
状态没有添加add
添加add了,没有提交commit
添加add了,提交commit之后就无没有提交的了。
查看版本记录:
$ git log
第2次编辑lx_code.txt,修改内容
添加一行
555
3.2.3 回到当前某前一个版本(version3回退到version2 向前回退)
HEAD^表示当前版本的【前】一个版本,
HEAD^^表示当前版本的【前前】个版本,
也可以使用HEAD~1表示当前版本的前一个版本,
HEAD~100表示当前版本的前100版本。
从version2回退到version1
$ git reset --hard HEAD~1
LUOLEI@DESKTOP-SBABRDF MINGW64 /f/lxgit (master)
$ git reset --hard HEAD~1
HEAD is now at e93592b version2 添加了一行444
当前文件内容,发现已经回退到version2
3.2.4 回到某一个版本(version2回退到version3 向后回退)
我们可以通过版本号回退,
git reset --hard 版本号
版本号就是commit后面长长的一串。
为什么使用通过版本号回退?不使用下面命令?
$ git reset --hard HEAD~1
注意,上面命令表示回退到当前版本的【前一个版本】,我们需要向后回退。(version2的前一个版本是version1)。
重进终端的我们看不到version3的版本号,要如何知道version3版本号呢?
显示当前分支的最近几次提交
git reflog
就可以通过版本号回退
git reset --hard 版本号

LUOLEI@DESKTOP-SBABRDF MINGW64 /f/lxgit (master)
$ git reflog
e93592b (HEAD -> master) HEAD@{0}: reset: moving to HEAD~1
6bb9497 HEAD@{1}: commit: version3 第2次修改添加了一行555
e93592b (HEAD -> master) HEAD@{2}: commit: version2 添加了一行444
417cd62 HEAD@{3}: commit (initial): version1 初次提交
LUOLEI@DESKTOP-SBABRDF MINGW64 /f/lxgit (master)
$ git reset --hard 6bb9497
HEAD is now at 6bb9497 version3 第2次修改添加了一行555
LUOLEI@DESKTOP-SBABRDF MINGW64 /f/lxgit (master)
$ git log
commit 6bb9497703c4a3fc9500c1505d2c4a414a75a87a (HEAD -> master)
Author: luolei <1726420180@qq.com>
Date: Sun Jun 28 20:09:39 2020 +0800
version3 第2次修改添加了一行555
commit e93592beb734593407baaed855f776c52a50ede2
Author: luolei <1726420180@qq.com>
Date: Sun Jun 28 20:05:13 2020 +0800
version2 添加了一行444
commit 417cd6211d7a446e677bcc6eef10aed0597eda30
Author: luolei <1726420180@qq.com>
Date: Sun Jun 28 19:52:31 2020 +0800
version1 初次提交
LUOLEI@DESKTOP-SBABRDF MINGW64 /f/lxgit (master)
$ cat lx_code.txt
111
222
333
444
555
4. 工作区和暂存区、版本库
工作区(WorkingDirectory) 就是电脑中的目录,比如我们的lxgit,就是一个工作区。
版本库(Repository):工作区有一个隐藏目录.git,这个不属于工作区,是git的版本库。git的版本库中存了很多东西,其中最重要的就是stage(暂存区),或者叫index,还有Git为我们自动创建了第一个分支master,以及指向master的一个指针HEAD。
Git提交文件到版本库需要两步:
1、git add 把文件添加进去,实际上就是把文件添加到暂存区。
2、git commit提交更改,实际上就是把暂存区的所有内容提交到当前分支上。
暂存区有多个修改的文件add了,但是没提交commit
执行git commit就可以一次性把暂存区的所有修改提交到分支并创建一个版本。
5. 撤销修改
在文件lx_code.txt中添加一行
666
但是我发现606有错误,需要更改。
三种方法
1、修改内容,添加add、提交commit;
2、回到上一个版本 git reset --hard HEAD~1
3、使用撤销命令 git checkout -- lx_code.txt
On branch master
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: lx_code.txt
no changes added to commit (use "git add" and/or "git commit -a")
在分支主机上
未暂存以提交的更改:
(使用“git add<file>..”更新将提交的内容)
(使用“git checkout--<file>…”放弃工作目录中的更改)
修改:lx_code.txt
没有添加要提交的更改(使用“git add”和/或“git commit-a”)
撤销命令
git checkout -- lx_code.txt
两种情景:
1.
lx_code.txt在工作区修改后,还没有add放到暂存区,使用撤销就回到和版本库一模一样的状态。
2. lx_code.txt已经add放入暂存区了,接着又修改lx_code.txt,撤销就回到添加暂存区后的状态。
1. lx_code.txt在工作区修改后,还没有add放到暂存区,使用撤销就回到和版本库一模一样的状态。
LUOLEI@DESKTOP-SBABRDF MINGW64 /f/lxgit (master)
$ vim lx_code.txt
LUOLEI@DESKTOP-SBABRDF MINGW64 /f/lxgit (master)
$ cat lx_code.txt
111
222
333
444
555
666
LUOLEI@DESKTOP-SBABRDF MINGW64 /f/lxgit (master)
$ git status
On branch master
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: lx_code.txt
no changes added to commit (use "git add" and/or "git commit -a")
LUOLEI@DESKTOP-SBABRDF MINGW64 /f/lxgit (master)
$ git checkout -- lx_code.txt
LUOLEI@DESKTOP-SBABRDF MINGW64 /f/lxgit (master)
$ cat lx_code.txt
111
222
333
444
555
2. lx_code.txt已经add放入暂存区了,接着又修改lx_code.txt,撤销就回到添加暂存区后的状态。
LUOLEI@DESKTOP-SBABRDF MINGW64 /f/lxgit (master)
$ cat lx_code.txt
111
222
333
444
555
LUOLEI@DESKTOP-SBABRDF MINGW64 /f/lxgit (master)
$ vim lx_code.txt
LUOLEI@DESKTOP-SBABRDF MINGW64 /f/lxgit (master)
$ cat lx_code.txt
111
222
333
444
555
666
LUOLEI@DESKTOP-SBABRDF MINGW64 /f/lxgit (master)
$ git add lx_code.txt
LUOLEI@DESKTOP-SBABRDF MINGW64 /f/lxgit (master)
$ git status
On branch master
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
modified: lx_code.txt
LUOLEI@DESKTOP-SBABRDF MINGW64 /f/lxgit (master)
$ vim lx_code.txt
LUOLEI@DESKTOP-SBABRDF MINGW64 /f/lxgit (master)
$ cat lx_code.txt
111
222
333
444
555
666
777
LUOLEI@DESKTOP-SBABRDF MINGW64 /f/lxgit (master)
$ git checkout -- lx_code.txt
LUOLEI@DESKTOP-SBABRDF MINGW64 /f/lxgit (master)
$ cat lx_code.txt
111
222
333
444
555
666
6. 删除文件
add添加lx_a.txt
commit提交lx_a.txt
然后删除lx_a.txt rm lx_a.txt
再次commit提交lx_a.txt 此时版本中内容已经是最新。
版本库中恢复lx_a.txt文件,可查看撤销修改
LUOLEI@DESKTOP-SBABRDF MINGW64 /f/lxgit (master)
$ touch lx_a.txt
LUOLEI@DESKTOP-SBABRDF MINGW64 /f/lxgit (master)
$ git add lx_a.txt
LUOLEI@DESKTOP-SBABRDF MINGW64 /f/lxgit (master)
$ git commit -m 'v1 初次提交lx_a.txt'
[master 7b13fe0] v1 初次提交lx_a.txt
2 files changed, 1 insertion(+)
create mode 100644 lx_a.txt
LUOLEI@DESKTOP-SBABRDF MINGW64 /f/lxgit (master)
$ ls
lx_a.txt lx_code.txt
LUOLEI@DESKTOP-SBABRDF MINGW64 /f/lxgit (master)
bash: r: command not found
LUOLEI@DESKTOP-SBABRDF MINGW64 /f/lxgit (master)
$ rm lx_a.txt
LUOLEI@DESKTOP-SBABRDF MINGW64 /f/lxgit (master)
$ git status
On branch master
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)
deleted: lx_a.txt
no changes added to commit (use "git add" and/or "git commit -a")
7. 远程仓库 使用github
7.1 添加SSH账户
(1)注册、登录github账户 (最近登录老是500,多试几次吧)
使用github,由于本地Git仓库和github仓库之间的传输是通过SSH加密的,所以需要SSH Key。
1、本地创建SSH Key。
在用户主目录下(C:\Users\用户名),看看有没有.ssh目录,如果有,再看看这个目录下有没有id_rsa和id_rsa.pub这两个文件,如果有的话,直接跳过此如下命令;
如果没有,打开cmd命令行,输入如下命令创建SSH:
ssh-keygen -t rsa -C "xxx180@qq.com"
id_rsa是私钥,不能泄露,id_rsa.pub是公钥,这个无所谓。
2、在github上添加SSH Key
登录github,打开” settings”中的SSH Keys页面,然后点击“SSH and GPG keys”然后“New SSH key”,填上任意title,在Key文本框里黏贴id_rsa.pub文件公钥的内容。
这样公钥就添加成功了。
7.2 创建仓库repository
创建一个新的仓库repository
填写仓库信息
github最近老是500,多刷几次。
这就创建成功了。但是仓库没有内容。
我们可以在GitHub上手动修改README, LICENSE和.gitignore。也可以在本地 创建了然后再推送。
7.2.1 推送分支
从命令行把本地库的内容推送到远程,使用 git push命令,就是把当前分支master推送到远程。
git remote add origin https://github.com/githubluolei/lxgit.git
git push -u origin master
参数-u 将会关联到远程的master 分支上,以后就可以git push不指定参数了
命令理解:
$ git push origin
将当前分支推送到origin主机的对应分支。 如果当前分支只有一个追踪分支,那么主机名都可以省略。
$ git push
如果当前分支与多个主机存在追踪关系,那么这个时候-u选项会指定一个默认主机,这样后面就可以不加任何参数使用git push。
$ git push -u origin master
将本地的master分支推送到origin主机,同时指定origin为默认主机,后面就可以不加任何参数使用git push了。
不带任何参数的git push,默认只推送当前分支,这叫做simple方式。此外,还有一种matching方式,会推送所有有对应的远程分支的本地分支。git 2.0版本之前,默认采用matching方法,现在改为默认采用simple方式。
推送到远程需要登录。
推送成功。
github会给你发送邮件通知
A personal access token (git: https://github.com/ on DESKTOP-SBABRDF at 29-6月-2020 19:20) with gist and repo scopes was recently added to your account. Visit https://github.com/settings/tokens for more information.
个人访问令牌(git:https://github.com/在DESKTOP-SBABRDF(29-6月-2020 19:20)上,最近在您的帐户中添加了gist和repo范围。访问https://github.com/settings/tokens了解更多信息。
在github上看一下,内容有了。
只要本地作了提交,使用push命令就可将本地master分支的最新修改推送到github远程仓库上。不需要参数-u
git push origin master
7.3 克隆项目
使用clone命令 加上上面复制的连接。
$ git clone git@github.com:githubluolei/lxgit.git
可以看到已经将远程的项目,克隆到了本地。
他会提示你无法知道github.com的真是性,问你是否继续yes就好了。
The authenticity of host 'github.com (13.229.188.59)' can't be established.
RSA key fingerprint is SHA256:nThbg6kXUpJWGl7E1IGOCspRomTxdCARLviKw6E5SY8.
Are you sure you want to continue connecting (yes/no)?
主持人的真实性github.com网站(13.229.188.59)“无法确定。
RSA密钥指纹是SHA256:nThbg6kXUpJWGl7E1IGOCspRomTxdCARLviKw6E5SY8。
是否确实要继续连接(是/否)?
8. 分支管理
8.1 实际项目中如何使用Git做分支管理
摘抄自:https://blog.csdn.net/shusheng0007/article/details/80791849
主分支
实际开发中,一个仓库(通常只放一个项目)主要存在两条主分支:master与develop分支。这个两个分支的生命周期是整个项目周期。就是说,自创建出来就不会删除,会随着项目的不断开发不断的往里面添加代码。master分支是创建git仓库时自动生成的,随即我们就会从master分支创建develop分支,如下图所示。
master:这个分支最为稳定,这个分支代表项目处于可发布的状态。
例如王二狗向master分支合并了代码,那就意味着王二狗完成了此项目的一个待发布的版本,项目经理可以认为,此项目已经准备好发布新版本了。所以master分支不是随随便便就可以签入代码的地方,只有计划发布的版本功能在develop分支上全部完成,而且测试没有问题了才会合并到master上。
develop:作为开发的分支,平行于master分支。
例如王二狗要开发一个注册功能,那么他就会从develop分支上创建一个feature分支 fb-register(后面讲),在fb-register分支上将注册功能完成后,将代码合并到develop分支上。这个fb-register就完成了它的使命,可以删除了。项目经理看王二狗效率很高啊,于是:“二狗你顺带把登录功能也做了吧”。二狗心中暗暗骂道:日了个狗的,但是任务还的正常做,二狗就会重复上面的步骤:从develop分支上新创建一个名为fb-login的分支,喝杯咖啡继续开发,1个小时后登录功能写好了,二狗又会将这个分支的代码合并回develop分支后将其删除。
通过以上分析可以发现,我们可以使用Git hook 脚本自动发布发布新的版本,具体就是每当有代码从develop分支合并到master分支的时候,脚本就会自动触发,编译发布新的版本。
支持分支
这些分支都是为了程序员协同开发,以及应对项目的各种需求而存在的。这些分支都是为了解决某一个具体的问题而设立,当这个问题解决后,代码会合并回主分支develop或者master后删除,一般我们会人为分出三种分支。
Feature branches:这种分支和我们程序员日常开发最为密切,称作功能分支。
必须从develop分支创建,完成后合并回develop分支
具体事例可以参考上面王二狗完成登录注册功能时的做法。
Release branches:这个分支用来分布新版本。
从develop分支创建,完成后合并回develop与master分支。
这个分支上可以做一些非常小的bug修复,当然,你也可以禁止在这个分支做任何bug的修复工作,而只做版本发布的相关操作,例如设置版本号等操作,那样的话那些发现的小bug就必须放到下一个版本修复了。如果在这个分支上发现了大bug,那么也绝对不能在这个分支上改,需要Featrue分支上改,走正常的流程。
实例:王二狗开发完了登录注册功能后决定发一个版本V0.1,那么他先从develop分支上创建一个Release 分支release-v0.1,然后二狗在这个分支上把版本号等做了修改。正准备编译发布了,项目经理说:“二狗啊,你那个登录框好像向右偏移量1个像素,你可以调一下吗?”二狗心中有暗暗骂道:日了个狗,但是。。。你们懂得,功能还的正常改。不过二狗发现这个bug特别小,对项目其他部分不造成不可预知的问题,所以直接在release分支上改了,然后愉快的发布了版本1.0.版本上线后,二狗将这个分支分别合并回了develop与master分支,然后删除了这个分支。
Hotfix branches:这个分支主要为修复线上特别紧急的bug准备的。
必须从master分支创建,完成后合并回develop与master分支。
这个分支主要是解决线上版本的紧急bug修复的,例如突然版本V0.1上有一个致命bug,必须修复。那么我们就可以从master 分支上发布这个版本那个时间点 例如 tag v0.1(一般代码发布后会及时在master上打tag),来创建一个 hotfix-v0.1.1的分支,然后在这个分支上改bug,然后发布新的版本。最后将代码合并回develop与master分支。
实例:某天夜里二狗正在和女朋友嘿咻呢,突然项目经理打来电话:“二狗啊,线上出了个大问题,大量用户无法登录,客服电话已经被打爆了,你紧急处理一下”。二狗心中默默骂道:日了个狗,然后就爬起来去改代码了。二狗先找到master分支上tag v0.1 的地方,然后新建了hotfix-v0.1.1 分支,默默的修bug去了。经过一个多小时的奋战,终于修复了,然后二狗改了版本号,发布了新版本。二狗将这个分支分别合并回了develop与master分支后删除了这个分支。终于搞定了,回头看看床上的女票已经进入了梦乡,二狗贼心不死,上前挑逗,此刻女票将满腹怨气集于一点,使出凌空一脚将其登于床下,随后甩一枕于二狗,二狗会意,趋客厅,抱枕卧于沙发。。。
简单的理解分支的作用
假设你准备开发一个新功能,但是第一周你写了一部分立刻提交,由于代码还没写完,不完整的代码库会导致别人不能干活了。如果等代码全部写完再一次提交,又存在丢失每天进度的巨大风险。
现在有了分支,就不用怕了。你创建了一个属于你自己的分支,别人看不到,还继续在原来的分支上正常工作,而你在自己的分支上干活,想提交就提交,直到开发完毕后,再一次性合并到原来的分支上,这样,既安全,又不影响别人工作。
8.2 创建分支与合并分支
8.2.1 概念
(1)一开始的时候,master分支是一条线,git用master指向最新的提交,再用HEAD指向master,就能确定当前分支,以及当前分支的提交点;
每次提交,master分支都会向前移动一步,这样随着你不断提交,master分支的线也越来越长。
(2)当我们创建新的分支,例如dev时,git新建了一个指针叫dev,指向master相同的提交,再把HEAD指向dev,就表示当前分支在dev上;
git创建一个分支除了增加一个dev指针,改变HEAD的指向,工作区的文件都不需要改变。
(3)从创建分支dev开始,对工作区的修改和提就是针对dev分支了,比如新提交一次后,dev指针往前移动一步,而master指针是不会变的;
(4)当我们在dev上的开发工作完成了,就可以把dev合并到master上。git怎么合并呢?就是直接把master指向dev的当前提交,就完成了合并;
git合并分支和增加分支都是只需要增加或修改一些指针,所以很快。
(5)合并完分支后,就可以删除dev分支。删除dev分支就是把dev指针给删掉,删掉后,我们就剩下了一条master分支。
8.2.2 创建与合并分支操作
下面要用的命令
查看分支:git branch
创建分支:git branch name
切换分支:git checkout name
创建+切换分支:git checkout –b name
合并某分支到当前分支:git merge name
删除分支:git branch –d name
(1)项目克隆到本地之后,创建分支,创建一个lx_main.java文件并提交一个版本
git checkout 命令加上 –b参数表示创建并切换,相当于如下2条命令
git branch dev
git checkout dev
git branch 查看分支,会列出所有的分支,当前分支前面会添加一个星号。
LUOLEI@DESKTOP-SBABRDF MINGW64 /f/lxgit/lxgit (master)
$ cd /f/lxgit/lxgit/
LUOLEI@DESKTOP-SBABRDF MINGW64 /f/lxgit/lxgit (master)
$ git checkout -b lx_dev
Switched to a new branch 'lxlx_dev'
LUOLEI@DESKTOP-SBABRDF MINGW64 /f/lxgit/lxgit (lxlx_dev)
$ git branch
* lxlx_dev
master
LUOLEI@DESKTOP-SBABRDF MINGW64 /f/lxgit/lxgit (lxlx_dev)
$ touch lx_main.java
LUOLEI@DESKTOP-SBABRDF MINGW64 /f/lxgit/lxgit (lxlx_dev)
$ vim lx_main.java
LUOLEI@DESKTOP-SBABRDF MINGW64 /f/lxgit/lxgit (lxlx_dev)
$ ls
lx_a.txt lx_code.txt lx_main.java
LUOLEI@DESKTOP-SBABRDF MINGW64 /f/lxgit/lxgit (lxlx_dev)
$ cat lx_main.java
public class lxapp(){
}
LUOLEI@DESKTOP-SBABRDF MINGW64 /f/lxgit/lxgit (lxlx_dev)
$ git status
On branch lxlx_dev
Untracked files:
(use "git add <file>..." to include in what will be committed)
lx_main.java
nothing added to commit but untracked files present (use "git add" to track)
LUOLEI@DESKTOP-SBABRDF MINGW64 /f/lxgit/lxgit (lxlx_dev)
$ git add lx_main.java
LUOLEI@DESKTOP-SBABRDF MINGW64 /f/lxgit/lxgit (lxlx_dev)
$ git commit -m 'lx_main.java 初次提交'
[lxlx_dev 9678826] lx_main.java 初次提交
1 file changed, 3 insertions(+)
create mode 100644 lx_main.java
(3)推送前github上文件列表
(4)推送前github上分支文件列表
(5)推送分支,就是把该分支上的所有本地提交推送到远程库,推送时要指定本地分支名称,这样git就把该分支推送到远程库对应的远程分支上
git push origin lxlx_dev

(6)现在dev分支工作完成了,我们切换到主分支master上,查看文件列表,没有分支的文件
(7)把dev分支上的内容合并到分支master上
$ git merge lxlx_dev
(8)合并后的master推送到远程
git push origin master
(9)合并完成后,分支lxlx_dev就可以删除了
$ git branch -d lxlx_dev
8.2.3 如何解决冲突
远程克隆项目到本地,创建分支
创建fb-register分支并切换到该分支,修改lx_mian.java内容,添加一个注册方法。然后添加、提交。然后切换到master分支。

切换到master分支后,修改lx_mian.java内容,添加一个登录方法。然后添加、提交。

然后在master分支上来合并fb-register提示产生冲突。
查看分支的状态
在当前主分支查看冲突文件的内容
LUOLEI@DESKTOP-SBABRDF MINGW64 /f/lxgit/lxgit (master|MERGING)
$ cat lx_main.java
public class lxapp(){
<<<<<<< HEAD
public void Login(String username, String passwd){}
=======
public void Register(User user){}
>>>>>>> fb-register
}
解释:
Git用<<<<<<<,=======,>>>>>>>分隔、标记出不同分支冲突的内容,没有冲突的直接展示。
<<<<<<< HEAD 标记冲突开始,是指当前分支的冲突修改的内容,这里是master主分支。后面跟的是当前分支中冲突的内容。
======= 用来分隔两个分支修改的内容。
>>>>>>> fb-register 是指fb-register上修改的内容。是要合并过来的分支的名称。
本例场景:
项目经理让我开发注册功能,让同事B开发登录,同事B开发登录先开发完成了,提交到了主分支。我提交就产生了冲突。因为两个分支各自都分别有新的提交,并且编辑了同一个文件。
怎么解决?
需要手动合并,手动合并就是在自动合并不了之后的办法。一般是先跟对方沟通,然后人工合并冲突提交, 沟通很重要,不然把别人的代码删除了就不好了。
经验:
每次开发前先从 git 上拉取下来最新的代码在 master 上,在 master 基础上建立自己的分支,做的修改在分支提交。push 的代码服务器时候再次 pull master ,然后和本地分支进行合并 merge 后再次 push。这样即使修改同一个文件也不容易冲突。
分支策略:master主分支是非常稳定的,用来发布新版本,一般情况下不允许在上面直接修改,干活一般情况下需要在新建的分支上开发,干完后,比如上要发布,或者说分支代码稳定后可以合并到主分支master上。
在本地主分支上,手动合并文件lx_main.java
提交合并冲突代码后,提交到主分支。可以查看版本记录查看分支合并的情况。
查看版本记录, Merge f9df72c 6ddc6e4
冲突解决了,也提交到了主分支,就需要推送到远程。
合并后的master推送到远程
git push origin master
git log 状态下退出,英文状态下输入字母Q即可退出
8.2.4 分支管理
合并分支时,git一般会用Fast forward模式,但这种模式下,删除分支后,会丢掉分支信息。如果要强制禁用Fast forward模式,git就会在merge时生成一个新的commit,这样,从分支历史上就可以看出分支信息。
使用参数 -no-ff 来禁用”fast forward”模式。
步骤
1、创建一个并切换dev分支;
2、修改lx_main.java的内容,提交,然后切换回主分支;
3、然后合并主分支与dev分支,禁用fast forward合并,使用命令
$ git merge --no-ff -m '合并dev分支,禁用fast forward合并' dev
4、查看分支历史记录
$ git log --graph --pretty=oneline --abbrev-commit
我们删除的分支dev从分支历史上就可以看出分支信息。
修改密码方法后面不是分号,是一对大括号,写错了,凑合看。
8.2.4 恢复删除的分支
dev分支在上面已经删除了,我发现有bug,不想重新创建分支,怎么恢复?
因为上面使用了禁用”fast forward”模式,git给我们自动提交了一次,所以可以查看commit提交的信息。
查看历史记录,找到commit-id
$ git log --graph --pretty=oneline --abbrev-commit
以指定commit为基础创建新的分支
git check -b {branch-name} {commit-id}
例如
$ git branch recover_dev e970e4b
切换分支后,查看内容, 都还在。
8.2.5 Bug分支
上面lx_mian.java中修改密码方法后面不是分号,是一对大括号,写错了。正好是一个Bug。 然后recover_dev中函数体中还没有开发完成。
在git中每个bug都可以通过一个新的临时分支来修复,修复完成后,合并分支,然后将临时分支删除。
当你接到一个修复bug的任务时,你可以创建一个分支bug-02 来修复它,
但是,可能存在当前正在dev上进行的工作还没有提交。可能工作进行到一半时候,我们还无法提交,这时候需要怎么办?
分支recover_dev方法ModifyPassword在原有基础上,添加一行注释,如下,图中忘了展示。
public void ModifyPassword(String uname, String passwd1, String passwd2){
//开发中。
}
Git还提供了一个stash功能,可以把当前工作现场 ”隐藏起来”,等以后恢复现场后继续工作。
首先确定在哪个分支上修复bug,假定需要在master分支上修复,就需要在master创建临时分支
1、创建一个临时分支bug-02 来修复bug
bug修复完成后,提交
提交后切换到master分支上,并完成合并,最后删除bug-02分支。
现在,可以回到dev分支上继续工作了。工作区是干净的,刚才的隐藏的工作现场怎么恢复?
列出所有保存的工作现场,查看暂存区的所有暂存修改记录
git stash list
工作现场还在,Git把stash内容存起来了,需要恢复。
使用git stash pop,恢复的同时把stash内容也删除了。
git stash pop
从git栈中获取到最近一次stash进去的内容,恢复工作区的内容,获取之后,会删除栈中对应的stash。
由于可能会stash多次,git使用栈管理,我们可以使用git stash list查看所有的stash
LUOLEI@DESKTOP-SBABRDF MINGW64 /f/lxgit/lxgit (master)
$ cat lx_main.java
public class lxapp(){
public void Register(User user){}
public void Login(String username, String passwd){}
public void ModifyPassword(String uname, String passwd1, String passwd2){
<<<<<<< Updated upstream
//Bug fix completed.
=======
//▒▒▒▒▒С▒
>>>>>>> Stashed changes
}
}
解释
<<<<<<< Updated upstream 当前分支修改的。
>>>>>>> Stashed changes 是Stashed恢复现场要修改的。
recover_dev正在开发的就是方法ModifyPassword,然后我将recover_dev当前工作现场 ”隐藏起来”,新创建了一个分支bug-02,他们修改的同一方法,可能会出现这种情况。再恢复,肯定冲突。
8.2.5.1 stash冲突解决
使用git stash pop一般情况下是会删除存储记录的,但是有冲突的情况并不会删除。
两种解决方法:
1、备份我们修改后的文件,删除程序文件中我们所做的修改,重新pull,然后在用我们备份好的文件替换掉,再push上去即可。
2、可以git reset --hard放弃本地修改,然后就可以git pull了。但是不推荐使用gitreset --hard指令,太危险。
操作
备份lx_main.java
删除bug-02中修改文件的内容,如果不知道修改的啥,
使用$ cat lx_main.java
9. 多人使用git
当你从远程库克隆时候,Git自动会把本地的master分支和远程的master分支对应联系起来了,且远程库的默认名称是origin。
查看远程库
要查看远程库的信息
git remote
要查看远程库的详细信息
git remote –v
9.1 推送分支到远程
推送分支,就是把该分支上的所有本地提交推送到远程库,推送时要指定本地分支,这样,git就会把该分支推送到远程库对应的远程分支上,命令格式
在 7.2.1 推送分支 已经用了push将主分支master推送到github可参考
git push origin 分支名称例:
git push origin master
远程lx_main.java内容

本地

把本地更新的lx_main.java代码推送到远程库中
远程lx_main.java推送后内容
如果我想把本地分支recover_dev推送到远程,远程没有的话会新建
git push origin recover_dev
master分支是主分支,因此要时刻与远程同步。
一些修复bug临时的分支不需要推送到远程去,可先合并到主分支上,然后把主分支master推送到远程去。
9.2 远程分支上拉取代码
命令格式
git pull orgin 分支名称
例如
git pull orgin recover_dev
会把远程分支recover_dev上的代码下载并合并到本地所在分支。
我们先在github上修改lx_main.java
原内容
修改后
10. 公司中使用git
项目经理:首先搭建好项目框架,然后把项目框架代码放到服务器。
项目成员:
1、在自己的电脑上,生成ssh公钥(参考上面的),然后把公钥给项目经理,项目经理把它添加的服务器上面;
2、项目经理会给每个组员的远程仓库的地址,组员把代码clone到自己的电脑上;
3、刚克隆下来的recover_dev分支在本地也叫recover_dev,通常不建议直接在这个分支上开发,而是新建一个分支。
3.1、git checkout -b dev-01 //创建并切换到dev-01分支上
3.2、我们可以在dev-01上写代码,写完后可把代码提交到本地仓库,add和commit;
3.3、开发完成后我们可将dev-01分支合并到本地recover_dev分支上
3.3.1、切换到本地recover_dev分支
git checkout recover_dev
切换分之前,需先在dev-01上commit更改到本地仓库
3.3.2、本地dev分支更新
git pull origin recover_dev
先把最新的远程的recover_dev拉取下来。当你合并分支的时候,可能其他同事又提交了新的内容。
3.3.3、在本地recover_dev分支上去合并dev-01分支
git merge dev-01
4、提交本地dev到远程
git pull orgin recover_dev
为什么不直接在本地recover_dev分支上开发,而另创一个dev-01分支?
场景:当你直接在本地recover_dev分支上开发时,测试告诉你线上出了一个小bug你需要马上修改掉,这个bug很快就能解决,但是你的本地recover_dev分支还处于开发状态,甚至是编译都不能通过的状态,你需要注释你的修改或者再去重新拉一个recover_dev分支修改bug
但是当你只是在dev-01分支上开发时,你只需提交当前修改并切换到本地recover_dev分支上去修改就行了,修改完后切换dev-01继续开发即可。
经验
1、提交前先git pull 更新别人提交的代码,避免发生冲突。
2、分支切换前先commit保存修改到本地仓库,不然切换不会成功,强行切换会导致当前分支被覆盖。
3、文件名拒绝中文
11. 常用git命令
初始化本地仓库
git init本地仓库关联远程仓库
git remote add origin “git 地址”查看已关联的仓库
git remote -v切换关联仓库
如想要从HTTPS方式的关联仓库切换到SSH方式关联的仓库
取消关联
git remote remove origin重新关联
git remote add origin “git SSH方式的地址”
查看所有的分支:
git branch -a更新分支列表(当你不能查看到完整的分支列表时):
git fetch切换分支:
git checkout 分支名称创建分支:
git branch 分支名称强制删除分支(可删除当前分支)
git branch-D 分支名非强制删除分支(不可删除当前分支):
git branch -d 分支名创建并切换到新分支:
git checkout -b 分支名
克隆远程仓库的项目代码:
git clone “远程仓库地址”
克隆远程仓库指定分支的代码:
git clone “远程仓库地址”
拉取远程分支:
git pull 远程分支
提交变更到本地仓库:
git commit -m “修改注释”:
将你的分支推到远程仓库:
git push origin “本地分支名”:远程分支名
撤销本地commit:
查看commit_id
git log
git reset --hard commit_id
查看当前仓库的状态(你修改了哪些,哪些保存到了本地仓库,哪些没有):
git status
查看提交历史:
git log
添加所有新文件
git add -A 添加所有变化
git add -u 添加被修改(modified)和被删除(deleted)文件,不包括新文件(new)
git add . 添加新文件(new)和被修改(modified)文件,不包括被删除(deleted)文件
pull 和 clone 的区别
clone 是本地没有 repository 时,将远程 repository 整个下载到本地。
pull 是本地有 repository 时,将远程 repository 里新的 commit 数据(如有的话)下载过来,并且与本地代码merge。
git pull相当于git fetch和git merge。
是先从远程下载git项目里的文件,然后将文件与本地的分支进行merge。
修改注释
git commit --amend
修改文件。
vim的命令 wq保存并退出
删除项目上的git信息
rm -rf .git
12. IDEA下配置使用Git
http://www.leixingke.com/article/detail/qgwA8HVp
参考资料
[1] git https://blog.csdn.net/YJG7D314/article/details/104551896
[2] git https://blog.csdn.net/qq_36150631/article/details/81038485
[3] git stash和git stash pop https://blog.csdn.net/qq_36898043/article/details/79431168
[4] 常用 Git 命令清单 http://www.ruanyifeng.com/blog/2015/12/git-cheat-sheet.html
[5] Git 完整命令手册地址:http://git-scm.com/docs
[6] PDF 版命令手册:github-git-cheat-sheet.pdf