Open mambat opened 6 years ago
Git是目前世界上最先进的分布式版本控制系统(没有之一)。
Linus Torvalds Linux & Git Talk is cheap, show me the code. Software is like sex: it's better when it's free.
Linus Torvalds
版本控制是一种记录若干文件内容变化,以便将来查阅特定版本修订情况的系统。
猛戳Here
Git是分布式版本控制系统,同一个Git仓库,可以分布到不同的机器上。
最初,只有一台机器有一个原始版本库,此后,别的机器可以“Clone”这个原始版本库,而且每台机器的版本都是一样的,没有主次之分。
然而,实际情况往往是找一台电脑充当服务器的角色,7x24小时开机,交换大家的修改。
每个版本库都有一个 .git 目录,它是 Git 用来保存元数据和对象数据库的地方。该目录非常重要,每次克隆版本库的时候,实际拷贝的就是这个目录里面的数据。
从版本库中取出某个版本的所有文件和目录,用以开始后续工作的叫做工作目录。
所谓的暂存区域只不过是个简单的文件,一般都放在 Git 目录中。有时候人们会把这个文件叫做索引文件,不过标准说法还是叫暂存区域。
在工作目录中修改某些文件。
将修改后的文件保存到暂存区域。
提交更新,将保存在暂存区域的文件快照永久转储到 Git 目录中。
如果自上次取出后,作了修改但还没有放到暂存区域,就是已修改状态。
如果作了修改并已放入暂存区域,就属于已暂存状态。
如果是 Git 目录中保存着的特定版本文件,就属于已提交状态。
如果是还未纳入版本管理,就属于未跟踪状态。
Baidu一下,你就知道
Google一下,你就知道的太多了
``` mkdir gitlab-demo cd gitlab-demo git init ```
此方式用的不多,一般都采用克隆远程版本库的方式
克隆,顾名思义,远程版本库已存在
git clone git@gitlab.server:wanglei/gitlab-demo.git
首先明确一下,所有的版本控制系统,其实只能跟踪文本文件的改动,比如TXT文件,网页,所有的程序代码等等,Git也不例外。而图片、视频这些二进制文件,虽然也能由版本控制系统管理,但没法跟踪文件的变化,只能把二进制文件每次改动串起来,也就是只知道图片从100KB改成了120KB,但到底改了啥,版本控制系统不知道,也没法知道。
touch README.md vi README.md git add README.md git commit -m "wrote a readme file"
选中待操作的文件或这个工程(注意文件颜色的变化)
Add to VCS
> ***一旦文件被Add to VCS,后续无需再Add: IDEA会在文件被修改后,自动进行Add***
git status
git log --pretty=oneline
git diff
git diff --cached
git diff HEAD
git diff HEAD -- GroupBean.java
已提交的不同版本之间的差异:
未提交与已提交最新版本之间的差异:
当你改乱了工作区某个文件的内容,而且已经添加到了暂存区时,想丢弃修改:
git reset HEAD file
git checkout -- file
Note: 如果直接执行git checkout -- file,则文件回到与暂存区一致的状态
当你改乱了工作区某个文件的内容,还未添加到暂存区时,想丢弃修改:
Note: IDEA会自动Add(stage)
通常需要先查看版本提交日志
可以通过从当前版本(HEAD)回退N个版本的方式进行版本回退
git reset --hard HEAD^
git reset --hard HEAD^^
git reset --hard HEAD~N
也可以回退到指定版本(双向的)
git reset --hard 3628164
撤销回退:git log无法获得被回退了的版本号,可通过git reflog查看我们的操作历史,从中可以得到被回退的版本号信息
git log
git reflog
Note: 注意HEAD、master、origin master指针的变化
To Commit 中输入回退目标版本号,默认为HEAD
git rm file
git commit -m "彻底删除file"
git rm --cached file
git commit -m "版本库中删除,工作目录中保留file"
rm file
Note: IDEA只支持本地工作目录和版本库同时删除
本地删除file,然后Commit Changes
版本库根目录下创建文件: .gitignore
``` target .DS_Store .idea *.iml ```
几乎每一种版本控制系统都以某种形式支持分支。
使用分支意味着你可以从开发主线上分离开来,然后在不影响主线的同时继续工作,开发完成后,再一次性合并到开发主线上。
在很多版本控制系统中,这是个昂贵的过程,常常需要创建一个源代码目录的完整副本,对大型项目来说会花费很长时间。
但Git的分支是与众不同的,无论创建、切换和删除分支,Git在1秒钟之内就能完成!
Git 的开发者都喜欢以这种方式来开展工作:
在master 分支中保留完全稳定的代码,即已经发布或即将发布的代码。
与此同时,他们还有一个名为develop分支 专门用于后续的开发,或仅用于稳定性测试。当然并不是说一定要绝对稳定,不过一旦进入某种稳定状态,便可以把它合并到master分支。
还有在工作中,将开发任务分解为各个功能或者模块,用topic分支(topic branch主题分支,有又称为feature branch特性分支),
Git默认只有一个分支,交主分支,即master分支。所有向master分支的提交可以串成一条时间线,如下:
创建分支:git checkout -b feature1,相当于git branch feature1和git checkout feature1
git checkout -b feature1
git branch feature1
git checkout feature1
查看分支:git branch,当前分支前面会标一个*号
git branch
*
合并分支分四步:
1. 切换到目标分支,如将feature1分支合并到master分支:git checkout master 2. 执行合并:git merge feature1 3. 如果存在冲突,则需要先处理冲突,然后再进行commit 3. 合并完成后,就可以放心地删除本地feature1分支了:git branch -d dev 4. 如果存在远程feature1分支,也可以将其删除:git push origin :feature1
创建分支
查看和切换分支
在feature1分支上进行修改提交后,新的分支图如下
合并分支
切换至目标分支
执行合并:feature1分支 -> Merge
如果存在冲突,则需要首先解决冲突再合并(左侧为目标分支,右侧为待合并分支,中间为合并结果)
冲突解决后,在目标分支上再进行commit
合并完成后,可删除本地分支、远程分支
开发新功能的过程中,如果需要及时解决线上的一个Bug,但是目前新开发的代码又不能提交,该怎么办?
git stash
git checkout master git checkout -b issue-001 ... git add -A git commit -m "fix bug 001"
git checkout dev git stash list git stash apply stash@{0} git stash drop stash@{0}
Note: git stash pop恢复至最近一次stash,同时将该stash删除
git stash pop
团队开发中,为了方便的交换大家的代码,通常需要搭建一个Git服务器,团队所有人都可以7x24访问。
服务器上创建的版本库,我们称之为远程版本库,所有人将本地版本库的修改推送至远程版本库。
Git服务器需要提供用户注册、权限管理、版本库管理、代码预览、issue跟踪等功能,常见的Git服务器如下:
很简单,可以去GitHub练练手。
Note: 通过Clone方式创建的本地版本库,不需要此步骤。
git remote add origin git@gitlab.server:wanglei/gitlab-demo.git
IDEA Git不支持add remote repository,需要在命令行中进行处理。
Note:通过Clone方式创建的本地版本库 无需指定-u参数、将本地分支与远程分支关联起来
git push -u origin master
若远程库是空的,第一次推送时需指定具体的分支:
当你的小伙伴已经向远程分支推送了他的提交,而碰巧你也对同样的文件作了修改,那么你再推送时会失败,因为你的小伙伴的最新提交和你试图推送的提交有冲突。
那么此时你就需要将远程最新的提交抓取下来,然后再本地合并,解决冲突再提交。
将本地分支与远程分支关联起来
git branch --set-upstream dev origin/dev
抓取并合并最新提交,合并冲突
git pull
提交并推送远程
git commit -m "merge and fix xxx" git push origin dev
Warn: pull前必须对当前修改进行commit或者stash,否则pull无法进行。
pull
通常,版本库的master分支只有少数人能够直接推送,其他人只能通过创建Feature分支、像Master分支提交Merge Request的方式来提交代码。
提交Merge Request时,可以指定受理人,受理人会收到相应的Merge Request邮件,然后进行处理:
git fetch origin
git log master..origin/feature1
git checkout master git merge origin/feature1 ###### 如果合并后测试有问题,则进行回退 git reset --hard HEAD^ 或 master@{1} ###### 推送远程 git push
Note: Merge Changes前最好对当前本地的修改进行commit或者stash。 Command Line环境下,如果本地存在未提交的变更,则无法进行后续的Merge操作。 IDEA中,则提供了Smart Merge功能,原理就是自动帮你Stash & UnStash。 也可以在Branch视图中,选择对应的Remote Branch,进行Merge操作。
Note:
Merge Changes
Smart Merge
Stash
UnStash
选中要合并的分支,执行合并
合并完成后,推送远程
Note: 需要到Git服务器提供的Web界面进行Merge Request的发起和关闭。 Merge Request可以保证代码Review
发送注册申请邮件给GitLab管理员,邮箱为wanglei20121208@gmail.com,邮件正文给出注册使用的邮箱地址。
注册申请成功后,GitLab会将用户名、初始密码发送至你的注册邮箱。
首次登录GitLab时,会强制重置密码,修改密码后重新登录即完成注册。
GitLab支持Http和SSH两种传输协议:
与GitLab建立互信的步骤如下:
生成SSH密钥对
ssh-keygen -t rsa -C "你的注册邮箱",一路回车即可。
最终在~/.ssh/下会生成id_rsa、id_rsa.pub两个文件
将SSH公钥添加到 GitLab SSH Keys 中。(在User Profile中)
id_rsa.pub中存放的即为SSH公钥
修改/etc/hosts
115.28.91.188 gitlab.server
修改SSH默认端口
由于Docker Container无法Link到Host主机的22端口(SSH默认端口),所以这里GitLab使用的端口为10022。
但Git默认使用的端口即为22端口,所以需要设置在SSH GitLab时使用特定端口(这里为10022)
vi ~/.ssh/config,内容如下
Host gitlab.server Port 10022 Host * Port 22
测试
ssh -Tvvv git@gitlab.server
当看到Welcome to GitLab, xxx和Exit status 0时表示SSH配置成功。
Welcome to GitLab, xxx
Exit status 0
Git简介
Git是什么?
什么是版本控制系统(VCS)?
版本控制是一种记录若干文件内容变化,以便将来查阅特定版本修订情况的系统。
集中式vs分布式
猛戳Here
Git是分布式版本控制系统,同一个Git仓库,可以分布到不同的机器上。
最初,只有一台机器有一个原始版本库,此后,别的机器可以“Clone”这个原始版本库,而且每台机器的版本都是一样的,没有主次之分。
然而,实际情况往往是找一台电脑充当服务器的角色,7x24小时开机,交换大家的修改。
为什么 Git 比 SVN 好
猛戳Here
Git基础
每个版本库都有一个 .git 目录,它是 Git 用来保存元数据和对象数据库的地方。该目录非常重要,每次克隆版本库的时候,实际拷贝的就是这个目录里面的数据。
从版本库中取出某个版本的所有文件和目录,用以开始后续工作的叫做工作目录。
所谓的暂存区域只不过是个简单的文件,一般都放在 Git 目录中。有时候人们会把这个文件叫做索引文件,不过标准说法还是叫暂存区域。
基本的 Git 工作流程如下:
在工作目录中修改某些文件。
将修改后的文件保存到暂存区域。
提交更新,将保存在暂存区域的文件快照永久转储到 Git 目录中。
我们可以从文件所处的位置来判断其状态:
如果自上次取出后,作了修改但还没有放到暂存区域,就是已修改状态。
如果作了修改并已放入暂存区域,就属于已暂存状态。
如果是 Git 目录中保存着的特定版本文件,就属于已提交状态。
如果是还未纳入版本管理,就属于未跟踪状态。
安装Git
Baidu一下,你就知道
Google一下,你就知道的太多了
创建版本库
本地初始化版本库(从无到有)
Command Line
Intellij IDEA
克隆远程版本库(从有到多)
克隆,顾名思义,远程版本库已存在
Command Line
Intellij IDEA
把文件添加到版本库
首先明确一下,所有的版本控制系统,其实只能跟踪文本文件的改动,比如TXT文件,网页,所有的程序代码等等,Git也不例外。而图片、视频这些二进制文件,虽然也能由版本控制系统管理,但没法跟踪文件的变化,只能把二进制文件每次改动串起来,也就是只知道图片从100KB改成了120KB,但到底改了啥,版本控制系统不知道,也没法知道。
Command Line
Intellij IDEA
选中待操作的文件或这个工程(注意文件颜色的变化)
Add to VCS
查看文件状态
Command Line
git status
Intellij IDEA:
查看提交日志
Command Line
git log --pretty=oneline
Intellij IDEA
查看文件变化
Command Line
git diff
git diff --cached
git diff HEAD
git diff HEAD -- GroupBean.java
Intellij IDEA
已提交的不同版本之间的差异:
未提交与已提交最新版本之间的差异:
撤销修改
Command Line
当你改乱了工作区某个文件的内容,而且已经添加到了暂存区时,想丢弃修改:
git reset HEAD file
,对文件进行unstagegit checkout -- file
,文件回到与版本库一致的状态当你改乱了工作区某个文件的内容,还未添加到暂存区时,想丢弃修改:
git checkout -- file
Intellij IDEA
版本回退
Command Line
通常需要先查看版本提交日志
可以通过从当前版本(HEAD)回退N个版本的方式进行版本回退
git reset --hard HEAD^
,回退一个版本git reset --hard HEAD^^
,回退两个版本git reset --hard HEAD~N
,回退N个版本也可以回退到指定版本(双向的)
git reset --hard 3628164
撤销回退:
git log
无法获得被回退了的版本号,可通过git reflog
查看我们的操作历史,从中可以得到被回退的版本号信息Intellij IDEA
To Commit 中输入回退目标版本号,默认为HEAD
删除文件
Command Line
git rm file
&git commit -m "彻底删除file"
,从版本库和工作目录中同时删除file文件。git rm --cached file
&git commit -m "版本库中删除,工作目录中保留file"
,从暂存区删除file文件,从而实现版本库中删除,工作目录中保留的目的。rm file
,可以通过git checkout -- file
恢复Intellij IDEA
本地删除file,然后Commit Changes
Ignore Files
版本库根目录下创建文件: .gitignore
Git分支
几乎每一种版本控制系统都以某种形式支持分支。
使用分支意味着你可以从开发主线上分离开来,然后在不影响主线的同时继续工作,开发完成后,再一次性合并到开发主线上。
在很多版本控制系统中,这是个昂贵的过程,常常需要创建一个源代码目录的完整副本,对大型项目来说会花费很长时间。
但Git的分支是与众不同的,无论创建、切换和删除分支,Git在1秒钟之内就能完成!
Git 的开发者都喜欢以这种方式来开展工作:
在master 分支中保留完全稳定的代码,即已经发布或即将发布的代码。
与此同时,他们还有一个名为develop分支 专门用于后续的开发,或仅用于稳定性测试。当然并不是说一定要绝对稳定,不过一旦进入某种稳定状态,便可以把它合并到master分支。
还有在工作中,将开发任务分解为各个功能或者模块,用topic分支(topic branch主题分支,有又称为feature branch特性分支),
创建与合并分支
Git默认只有一个分支,交主分支,即master分支。所有向master分支的提交可以串成一条时间线,如下:
Command Line
创建分支:
git checkout -b feature1
,相当于git branch feature1
和git checkout feature1
查看分支:
git branch
,当前分支前面会标一个*
号合并分支分四步:
Intellij IDEA
创建分支
查看和切换分支
在feature1分支上进行修改提交后,新的分支图如下
合并分支
切换至目标分支
执行合并:feature1分支 -> Merge
如果存在冲突,则需要首先解决冲突再合并(左侧为目标分支,右侧为待合并分支,中间为合并结果)
冲突解决后,在目标分支上再进行commit
合并完成后,可删除本地分支、远程分支
Stash & Unstash
将当前工作目录保存下来,以备后续恢复后继续工作
Command Line
git stash
Intellij IDEA
基于master创建bug修复分支issue-001
恢复工作目录(假设之前的工作分支为dev)
Command Line
Intellij IDEA
远程版本库
团队开发中,为了方便的交换大家的代码,通常需要搭建一个Git服务器,团队所有人都可以7x24访问。
服务器上创建的版本库,我们称之为远程版本库,所有人将本地版本库的修改推送至远程版本库。
Git服务器
Git服务器需要提供用户注册、权限管理、版本库管理、代码预览、issue跟踪等功能,常见的Git服务器如下:
Git服务器创建版本库
很简单,可以去GitHub练练手。
添加远程版本库
IDEA Git不支持add remote repository,需要在命令行中进行处理。
推送分支
Command Line
Intellij IDEA
若远程库是空的,第一次推送时需指定具体的分支:
抓取分支
当你的小伙伴已经向远程分支推送了他的提交,而碰巧你也对同样的文件作了修改,那么你再推送时会失败,因为你的小伙伴的最新提交和你试图推送的提交有冲突。
那么此时你就需要将远程最新的提交抓取下来,然后再本地合并,解决冲突再提交。
Command Line
将本地分支与远程分支关联起来
抓取并合并最新提交,合并冲突
提交并推送远程
Intellij IDEA
抓取并合并最新提交,合并冲突
提交并推送远程
Merge Request
通常,版本库的master分支只有少数人能够直接推送,其他人只能通过创建Feature分支、像Master分支提交Merge Request的方式来提交代码。
提交Merge Request时,可以指定受理人,受理人会收到相应的Merge Request邮件,然后进行处理:
更新远程仓库数据
Command Line
git fetch origin
Intellij IDEA
查看Merge Request的修改记录
Command Line
git log master..origin/feature1
Intellij IDEA
如若接受Merge Request,则在本地进行合并
Command Line
Intellij IDEA
选中要合并的分支,执行合并
合并完成后,推送远程
加入GitLab
注册
发送注册申请邮件给GitLab管理员,邮箱为wanglei20121208@gmail.com,邮件正文给出注册使用的邮箱地址。
注册申请成功后,GitLab会将用户名、初始密码发送至你的注册邮箱。
首次登录GitLab时,会强制重置密码,修改密码后重新登录即完成注册。
协议
GitLab支持Http和SSH两种传输协议:
SSH协议
与GitLab建立互信的步骤如下:
生成SSH密钥对
ssh-keygen -t rsa -C "你的注册邮箱",一路回车即可。
最终在~/.ssh/下会生成id_rsa、id_rsa.pub两个文件
将SSH公钥添加到 GitLab SSH Keys 中。(在User Profile中)
id_rsa.pub中存放的即为SSH公钥
修改/etc/hosts
115.28.91.188 gitlab.server
修改SSH默认端口
由于Docker Container无法Link到Host主机的22端口(SSH默认端口),所以这里GitLab使用的端口为10022。
但Git默认使用的端口即为22端口,所以需要设置在SSH GitLab时使用特定端口(这里为10022)
vi ~/.ssh/config,内容如下
测试
ssh -Tvvv git@gitlab.server
当看到
Welcome to GitLab, xxx
和Exit status 0
时表示SSH配置成功。Enjoy the Git