Git原理及使用

在学习Git的过程中,本人合并以及适当修改了以下几篇文章的内容:

一篇文章,教你学会Git

MAC上Git安装与GitHub基本使用

git - 简明指南

视频同步笔记:狂神聊Git

Git环境配置

下载

下载步骤略去,在官网下载即可,参考MAC上Git安装与GitHub基本使用

配置

安装完git后首先要配置git用户名和邮箱,非常重要,因为每次git提交都需要用到该信息,被永远的嵌入到了你的提交中

git config --global user.name "用户名" # 设置用户名
git config --global user.email "邮箱地址" # 设置邮箱email

--global的作用:

如果加上--global,则表明这是全局设置,git将总是会使用该配置信息来处理你在系统中所做的一切操作。如果希望在一个特定的项目中使用不同的名称或e-mail地址,你可以在该项目中运行git config命令而不加--global选项。总之--global为全局配置,不加为某个项目的特定配置。

查看配置

git config -l --system # 查看系统配置
git config -l --global # 查看用户配置

git配置实质上都是**本地文件**:(以Mac OS为例)系统配置文件为/usr/local/git/etc/gitconfig,用户配置文件为~/.gitconfig注意,用户配置文件必须在设置了全局配置信息后才会被创建

Git工作原理

Git工作区域

  • 工作目录(Working Directory):平时存放项目代码的地方
  • 暂存区(Stage/Index):暂存区,用于临时存放你的改动,事实上它只是一个文件,保存即将提交到文件列表信息
  • 本地仓库 / 资源库(Repository或Git Directory):就是安全存放数据的位置,这里面有你提交到所有版本的数据。其中HEAD指向最新放入仓库的版本(最新一次commit
  • 远程仓库(Remote Directory):远程仓库,托管代码的服务器,可以简单的认为是你项目组中的一台电脑用于远程数据交换

本地区域的一些概念

  • Directory:使用Git管理的一个目录,也就是一个仓库,包含我们的工作空间和Git的管理空间
  • WorkSpace:需要通过Git进行版本控制的目录和文件,这些目录和文件组成了工作空间。
  • .git:存放Git管理信息的目录,初始化仓库(git init命令)的时候自动创建。
  • Index/Stage:暂存区,或者叫待提交更新区,在提交进入repo之前,我们可以把所有的更新放在暂存区。
  • Local Repo:本地仓库,一个存放在本地的版本库;HEAD会指示当前的开发分支(branch)。
  • Stash:隐藏,是一个工作状态保存栈,用于保存/恢复WorkSpace中的临时状态。

Git工作流程

  1. 在工作目录中新建、修改、删除文件
  2. 将需要进行版本管理的文件放入暂存区域
  3. 将暂存区域的文件push到git远程仓库

git管理的文件有三种状态:modified(已修改)staged(已暂存)committed(已提交)

Git文件状态

文件的四种状态

  • Untracked: 未跟踪, 此文件在文件夹中, 但并没有加入到git库, 不参与版本控制. 通过git add 状态变为Staged.
  • Unmodify: 文件已经入库, 未修改, 即版本库中的文件快照内容与文件夹中完全一致. 这种类型的文件有两种去处, 如果它被修改, 而变为Modified. 如果使用git rm移出版本库, 则成为Untracked文件
  • Modified: 文件已修改, 仅仅是修改, 并没有进 行其他的操作. 这个文件也有两个去处, 通过git add可进入暂存staged状态, 使用git checkout 则丢弃修改过, 返回到unmodify状态, 这个git checkout即从库中取出文件, 覆盖当前修改 !
  • Staged: 暂存状态. 执行git commit则将修改同步到库中, 这时库中的文件和本地文件又变为一致, 文件为Unmodify状态. 执行git reset HEAD filename取消暂存, 文件状态为Modified

Git实操演练

相关常见的操作命令如下图所示

本地仓库的操作

创建本地仓库,有两种方法。一种是创建全新的仓库,另一种是克隆远程仓库

创建全新仓库

[bxy@Yu]Desktop$ mkdir git_test
[bxy@Yu]Desktop$ cd git_test

[bxy@Yu]git_test$ git init # 初始化Git仓库,执行完成后,会多出一个.git的目录

克隆远程仓库

[bxy@Yu]Desktop$ git clone [远程仓库的url] # 克隆一个项目和它的整个代码历史(版本信息)

接下来,实际操作一个例子(git_test目录已执行过git init命令)

[bxy@Yu]git_test$ touch hello.java # 新建一个hello.java文件

[bxy@Yu]git_test$ git status # 查看文件状态 也可以在后面加上文件名
[bxy@Yu]git_test$ git add . # 添加所有文件到暂存区

[bxy@Yu]git_test$ git status # 查看文件状态
[bxy@Yu]git_test$ git commit -m "This is my new java file!!" # 提交暂存区中的内容到本地仓库 -m 提交信息

[bxy@Yu]git_test$ git status # 查看文件状态

远程仓库的操作

SSH公钥的生成

在本机生成公钥(id_rsa.pub)和私钥(id_rsa),具体操作流程见我另一篇文章SSH免密登陆操作及相关文件作用,这里不再赘述

Github设置
  1. 右上角个人头像 -> Settings -> SSH and GPG keys -> New SSH key

    ~/.ssh/id_rsa.pub文件内容粘贴到「公钥」对应文本框中,输入Title,点击确定后,输入Github密码,添加成功

  2. 验证链接

    ssh -T git@github.com
    
  3. 提交本地项目到远程仓库(git push

    新建一个仓库(git_test_rep),复制SSH地址,在命令行键入

    git clone [url]
    

    # 在git_test_rep中新建一个文件
    [bxy@Yu]git_test_rep$ touch hello.java
    
    # 添加到暂存区
    [bxy@Yu]git_test_rep$ git add .
    
    # 提交到本地仓库
    [bxy@Yu]git_test_rep$ git commit -m "First commit"
    
    # 推送到远程仓库(Github中)
    [bxy@Yu]git_test_rep$ git push
    

    Github中刷新,发现新文件已被成功推送

    注意:【从Github中克隆下来的仓库项目,在.git目录下的config文件中已配置好远程仓库的位置信息,git push命令后面无需加远程仓库url】

Git操作命令

add

git add .添加当前目录的所有文件到暂存区
git add [dir]添加指定目录到暂存区,包括子目录
git add [file1]添加指定文件到暂存区

commit

git commit -m [message]交暂存区到本地仓库,message代表说明信息
git commit [file1] -m [message]提交暂存区的指定文件到本地仓库
git commit --amend -m [message]用一次新的commit,替代上一次提交

push

git push [remote] [branch]上传本地指定分支到远程仓库
git push [remote] --force强行推送当前分支到远程仓库,即使有冲突
git push [remote] --all推送所有分支到远程仓库

branch

git branch列出所有本地分支
git branch -r列出所有远程分支
git branch -a列出所有本地分支和远程分支
git branch [branch-name]新建一个分支,但依然停留在当前分支
git checkout -b [branch-name]新建一个分支,并切换到该分支
git branch --track [branch] [remote-branch]新建一个分支,与指定的远程分支建立追踪关系
git checkout [branch-name]切换到指定分支,并更新工作区
git branch -d [branch-name]删除分支
git push origin --delete [branch-name]删除远程分支

merge

git fetch [remote]merge之前先拉一下远程仓库最新代码
git merge [branch]合并指定分支到当前分支

一般在merge之后,会出现conflict,需要针对冲突情况,手动解除冲突。主要是因为两个用户修改了同一文件的同一块区域。

rebase

rebase又称为衍合,是合并的另外一种选择。

在开始阶段,我们处于new分支上,执行git rebase dev,那么new分支上新的commit都在master分支上重演一遍,最后checkout切换回到new分支。这一点与merge是一样的,合并前后所处的分支并没有改变。git rebase dev,通俗的解释就是new分支想站在dev的肩膀上继续下去。rebase也需要手动解决冲突。

rebase与merge的区别

现在我们有这样的两个分支,test和master,提交如下:

      D---E test
     /
A---B---C---F master复制代码

在master执行git merge test,然后会得到如下结果:

      D--------E
     /          \
A---B---C---F----G   test, master复制代码

在master执行git rebase test,然后得到如下结果:

A---B---D---E---C'---F'   test, master复制代码

可以看到,merge操作会生成一个新的节点,之前的提交分开显示。而rebase操作不会生成新的节点,是将两个分支融合成一个线性的提交。

如果你想要一个干净的,没有merge commit的线性历史树,那么你应该选择git rebase
如果你想保留完整的历史记录,并且想要避免重写commit history的风险,你应该选择使用git merge

reset

reset命令把当前分支指向另一个位置,并且相应的变动工作区和暂存区。

git reset —soft [commit]只改变提交点,暂存区和工作目录的内容都不改变
git reset —mixed [commit]改变提交点,同时改变暂存区的内容
git reset —hard [commit]暂存区、工作区的内容都会被修改到与提交点完全一致的状态
git reset --hard HEAD让工作区回到上次提交时的状态

revert

git revert用一个新提交来消除一个历史提交所做的任何修改。

revert与reset的区别

git revert是用一次新的commit来回滚之前的commit,git reset是直接删除指定的commit。

在回滚这一操作上看,效果差不多。但是在日后继续merge以前的老版本时有区别。因为git revert是用一次逆向的commit“中和”之前的提交,因此日后合并老的branch时,导致这部分改变不会再次出现,减少冲突。但是git reset是之间把某些commit在某个branch上删除,因而和老的branch再次merge时,这些被回滚的commit应该还会被引入,产生很多冲突。关于这一点,不太理解的可以看这篇文章

git reset 是把HEAD向后移动了一下,而git revert是HEAD继续前进,只是新的commit的内容和要revert的内容正好相反,能够抵消要被revert的内容。

diff

git diff显示工作区和暂存区的差异
git diff HEAD显示工作区与当前分支最新commit之间的差异

其他

git status显示有变更的文件
git status [file-name]显示文件的状态
git cherry-pick [commit]选择一个commit,合并进当前分支

Git补充

HEAD的理解

HEAD,它始终指向当前所处分支的最新的提交点。你所处的分支变化了,或者产生了新的提交点,HEAD就会跟着改变。

Git忽略的文件

有些时候我们不想把某些文件纳入版本控制中,比如数据库文件,临时文件,设计文件等。

在主目录下建立".gitignore"文件,此文件有如下规则:

  1. 文件中的空行或以#开始注释行将不起作用
  2. 可以使用Linux通配符。例如:星号(*)代表任意多个字符,问号(?)代表一个字符,方括号([abc])代表可选字符范围,大括号({string1,string2,…})代表可选的字符串等。
  3. 如果名称的最前面有一个感叹号(!),表示例外规则,将不被忽略
  4. 如果名称的最前面是一个路径分隔符(/),和此名称同级的其他文件将被忽略,而不包括此名称下面的文件及目录
  5. 如果名称的最后面是一个路径分隔符(/),表示要忽略的是该名称目录下对应的所有文件及目录

举例:

# 为注释
*.txt        #忽略所有 .txt结尾的文件,这样的话上传就不会被选中!
!lib.txt     #但lib.txt除外
/temp        #仅忽略项目根目录下的所有文件,不会忽略temp目录
build/       #忽略build/目录下的所有文件
doc/*.txt    #会忽略 doc/notes.txt 但不包括 doc/server/arch.txt

版本控制

概念

版本控制(Revision Control)是一种在开发的过程中用于管理我们对文件、目录或工程等内容的修改历史,方便查看更改历史记录,备份以便恢复以前的版本的软件工程技术。

  • 实现跨区域多人协同开发
  • 追踪和记载一个或者多个文件的历史记录
  • 组织和保护你的源代码和文档
  • 统计工作量
  • 并行开发、提高开发效率
  • 跟踪记录整个软件的开发过程
  • 减轻开发人员的负担,节省时间,同时降低人为错误

简单说就是用于管理多人协同开发项目的技术。

没有进行版本控制或者版本控制本身缺乏正确的流程管理,在软件开发过程中将会引入很多问题,如软件代码的一致性、软件内容的冗余、软件过程的事物性、软件开发过程中的并发性、软件源代码的安全性,以及软件的整合等问题。

主流的版本控制器有如下这些:

  • Git
  • SVN(Subversion)
  • CVS(Concurrent Versions System)
  • VSS(Micorosoft Visual SourceSafe)
  • TFS(Team Foundation Server)
  • Visual Studio Online

版本控制产品非常的多(Perforce、Rational ClearCase、RCS(GNU Revision Control System)、Serena Dimention、SVK、BitKeeper、Monotone、Bazaar、Mercurial、SourceGear Vault),现在影响力最大且使用最广泛的是Git与SVN

SVN和Git的区别

SVN集中式版本控制系统,版本库是集中放在中央服务器的,而工作的时候,用的都是自己的电脑,所以首先要从中央服务器得到最新的版本,然后工作,完成工作后,需要把自己做完的活推送到中央服务器。集中式版本控制系统是必须联网才能工作,对网络带宽要求较高。

Git分布式版本控制系统,没有中央服务器,每个人的电脑就是一个完整的版本库,工作的时候不需要联网了,因为版本都在自己电脑上。协同的方法是这样的:比如说自己在电脑上改了文件A,其他人也在电脑上改了文件A,这时,你们两之间只需把各自的修改推送给对方,就可以互相看到对方的修改了。Git可以直接看到更新了哪些代码和文件!Git是目前世界上最先进的分布式版本控制系统。

参考资料

【狂神说Java】Git最新教程通俗易懂

一篇文章,教你学会Git

MAC上Git安装与GitHub基本使用

git - 简明指南

视频同步笔记:狂神聊Git

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值