加载中...
加载中...
Git使用教程(详细)

Git使用教程(详细) 原创

1. Git介绍

Git是目前世界上最先进的分布式版本控制系统。Git 不仅仅是个版本控制系统,它也是个内容管理系统(Software configuration management ,SCM),工作管理系统等。

git

git远程操作管理

git远程操作管理

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就好了,根据提示作相应改变。

装完msysgit后右键鼠标会多出一些选项来开始菜单里面找到 "Git Bash"

弹出来框框输入查看版本  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^^表示当前版本的【前前】个版本,

也可以使用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,多试几次吧)

官网  https://github.com/  

使用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

没有更多推荐了 [去首页]
image
文章
357
原创
284
转载
73
翻译
0
访问量
199056
喜欢
47
粉丝
6
码龄
5年
资源
0

文章目录

加载中...
0
2