Git 版本控制

版本控制

概述

版本控制是一种记录一个或若干文件内容变化,以便将来查阅特定版本修订情况的系统。

如果你是位图形或网页设计师,可能会需要保存某一幅图片或页面布局文件的所有修订版本(这或许是你非常渴望拥有的功能),采用版本控制系统(VCS)是个明智的选择。有了它你就可以将选定的文件回溯到之前的状态,甚至将整个项目都回退到过去某个时间点的状态,你可以比较文件的变化细节,查出最后是谁修改了哪个地方,从而找出导致怪异问题出现的原因,又是谁在何时报告了某个功能缺陷等等。使用版本控制系统通常还意味着,就算你乱来一气把整个项目中的文件改的改删的删,你也照样可以轻松恢复到原先的样子。但额外增加的工作量却微乎其微。

本地版本控制

许多人习惯用复制整个项目目录的方式来保存不同的版本,或许还会改名加上备份时间以示区别。这么做唯一的好处就是简单,但是特别容易犯错。 有时候会混淆所在的工作目录,一不小心会写错文件或者覆盖意想不到的文件。为了解决这个问题,人们很久以前就开发了许多种本地版本控制系统,大多都是采用某种简单的数据库来记录文件的历次更新差异。

其中最流行的一种叫做 RCS,现今许多计算机系统上都还看得到它的踪影。RCS 的工作原理是在硬盘上保存补丁集(补丁是指文件修订前后的变化);通过应用所有的补丁,可以重新计算出各个版本的文件内容。

集中化的版本控制系统

接下来人们又遇到一个问题,如何让在不同系统上的开发者协同工作?于是,集中化的版本控制系统(Centralized Version Control Systems,简称 CVCS)应运而生。这类系统,诸如 CVS、Subversion 以及 Perforce 等,都有一个单一的集中管理的服务器,保存所有文件的修订版本,而协同工作的人们都通过客户端连到这台服务器,取出最新的文件或者提交更新。多年以来,这已成为版本控制系统的标准做法。

这种做法带来了许多好处,特别是相较于老式的本地 VCS 来说。现在,每个人都可以在一定程度上看到项目中的其他人正在做些什么。而管理员也可以轻松掌控每个开发者的权限,并且管理一个 CVCS 要远比在各个客户端上维护本地数据库来得轻松容易。事分两面,有好有坏。这么做最显而易见的缺点是中央服务器的单点故障。如果宕机一小时,那么在这一小时内,谁都无法提交更新,也就无法协同工作。如果中心数据库所在的磁盘发生损坏,又没有做恰当备份,毫无疑问你将丢失所有数据——包括项目的整个变更历史,只剩下人们在各自机器上保留的单独快照。本地版本控制系统也存在类似问题,只要整个项目的历史记录被保存在单一位置,就有丢失所有历史更新记录的风险。

分布式版本控制系统

于是分布式版本控制系统(Distributed Version Control System,简称 DVCS)面世了。在这类系统中,像 Git、Mercurial、Bazaar 以及 Darcs 等,客户端并不只提取最新版本的文件快照, 而是把代码仓库完整地镜像下来,包括完整的历史记录。这么一来,任何一处协同工作用的服务器发生故障,事后都可以用任何一个镜像出来的本地仓库恢复。因为每一次的克隆操作,实际上都是一次对代码仓库的完整备份。

更进一步,许多这类系统都可以指定和若干不同的远端代码仓库进行交互。籍此,你就可以在同一个项目中,分别和不同工作小组的人相互协作。你可以根据需要设定不同的协作流程,比如层次模型式的工作流,而这在以前的集中式系统中是无法实现的。

概述

Git 是一个开源的分布式版本控制系统,是 Linus Torvalds 为了帮助管理 Linux 内核开发而开发的一个开放源码的版本控制软件,Git 可以使用本地创建仓库与网络仓库,解决了集中管理型版本控制软件存在的一些问题(CVS、VSS、SVN)。

官方网址:Git

Git 历史【了解】

同生活中的许多伟大事件一样,Git 诞生于一个极富纷争大举创新的年代。Linux 内核开源项目有着为数众广的参与者。绝大多数的 Linux 内核维护工作都花在了提交补丁和保存归档的繁琐事务上(1991-2002年间)。到 2002 年,整个项目组开始启用分布式版本控制系 BitKeeper 来管理和维护代码。

到 2005 年的时候,开发 BitKeeper 的商业公司同 Linux 内核开源社区的合作关系结束,他们收回了免费使用 BitKeeper 的权力。这就迫使 Linux 开源社区(特别是 Linux 的缔造者 Linus Torvalds )不得不吸取教训,只有开发一套属于自己的版本控制系统才不至于重蹈覆辙。他们对新的系统订了若干目标:

  • 速度

  • 简单的设计

  • 对非线性开发模式的强力支持(允许上千个并行开发的分支)

  • 完全分布式

  • 有能力高效管理类似 Linux 内核一样的超大规模项目(速度和数据量)

Git 目录【重点】

本地仓库

'Git目录' 一般就是指项目根目录下的.git目录,也叫做本地仓库。

'Git目录' 是为你的项目存储所有历史和元信息的目录 - 包括所有的对象,这些对象指向不同的分支。

每一个项目只能有一个“Git目录”(这和 SVN、CVS 的每个子目录中都有此类目录相反),这个叫.git的目录在你项目的根目录下(这是默认设置,但并不是必须的)。如果你查看这个目录的内容,你可以看所有的重要文件:

目录描述
HEAD当前git项目当前处在哪个分支里
config项目的配置信息,git config 命令会改动它
description项目的描述信息
hooks/系统默认钩子脚本目录
index索引文件
logs/各个refs的历史信息
objects/Git本地仓库的所有对象 (commits,trees,blobs,tags)
refs/标识你项目里的每个分支指向了哪个提交(commit)

工作目录

Git 的工作目录存储着你现在签出(checkout)来用来编辑的文件。当你在项目的不同分支间切换时,工作目录里的文件经常会被替换和删除。所有历史信息都保存在 Git 目录中,工作目录只用来临时保存签出(checkout)文件的地方,你可以编辑工作目录的文件直到下次提交(commit)为止。

暂存区

用于临时存放你的改动,事实上它只是一个文件,保存即将提交到文件列表信息,一般存放在"git目录"下的index文件(.git/index)中,所以我们把暂存区有时也叫作索引(index)。

示例图

Git 工作流程【了解】

一般工作流程如下:

1.从远程仓库中克隆 Git 资源作为本地仓库。

2.从本地仓库中 checkout 代码然后进行代码修改。

3.在提交前先将代码提交到暂存区。

4.提交修改。提交到本地仓库。本地仓库中保存修改的各个历史版本。

5.在修改完成后,需要和团队成员共享代码时,可以将代码 push 到远程仓库。

下图展示了 Git 的工作流程:

下载与安装

下载

下载地址:Git - Downloading Package

安装

初始化

Git 是分布式版本控制系统,所以需要填写用户名和邮箱作为一个标识,--global 表示全局属性,所有的 Git 项目都会共用属性。

-- 配置用户名和邮箱
$ git config --global user.name "用户名"
$ git config --global user.email "邮箱"
​
-- 案例
git config --global user.name "yyqx"
git config --global user.email "123456@qq.com" 

基本设置

查看配置

Git 自带一个 git config 的工具来帮助设置控制 Git 外观和行为的配置变量。

可以通过以下命令查看所有的配置以及它们所在的文件

git config --list --show-origin

文本编辑器

-- 格式
$ git config --global core.editor "路径"
​
-- 案例代码
git config --global core.editor "'D:\Notepad++\notepad++.exe' -multiInst -notabbar -nosession -noPlugin"

中文文件名显示

git config --global core.quotepath false

取消 SSL 验证

git config --global http.sslVerify false

文件忽略

项目中经常会生成一些Git系统不需要追踪(track)的文件。典型的是在编译生成过程中产生的文件或是编程器生成的临时备份文件。当然,你不追踪(track)这些文件,可以不用"git add"去把它们加到索引中。但是这样会很快变成一件烦人的事,你发现项目中到处有未追踪(untracked)的文件;这样也使 "git add ." 和 "git commit -a" 变得实际上没有用处,同时"git status"命令的输出也会有它们。

你可以在你的顶层工作目录中添加一个叫".gitignore"的文件,来告诉 Git 系统要忽略掉哪些文件。

# Compiled class file
*.class
​
# Log file
*.log
​
# BlueJ files
*.ctxt
​
# Mobile Tools for Java (J2ME)
.mtj.tmp/
​
# Package Files #
*.jar
*.war
*.ear
*.zip
*.tar.gz
*.rar
​
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
hs_err_pid*
​
# IntelliJ project files
.idea
*.iml
out
gen
/.apt_generated/
/.classpath
/.factorypath
/.project
/.settings/
/.springBeans
/target/
/.gitignore
/user-profile-analysis.iml
.DS_Store

基本用法

获得 Git 仓库

git init

添加到暂存区

git add

查看暂存区

git status

使用 git status 命令是查看索引内容的最简单办法。运行此命令就可以看到: 哪些文件被暂存了,哪些文件被修改了但是没有暂存,还有哪些文件没有被跟踪(untracked)。

从暂存区中删除

git rm --cached '文件名'

提交到本地仓库

git commit

# 携带注释提交
git commit –m

# 自动将所有内容被修改的文件(不包括新创建的文件)都添加到暂存区中,并同时提交
git commit -a

【补充】提交注释技巧

commit 注释最好以一行短句子作为开头,来简要描述一下这次 commit 所作的修改(最好不要超过50个字符);然后空一行再把详细的注释写清楚。这样就可以很方便的用工具把 commit 当做 email 通知,第一行作为标题,剩下的部分就作 email 的正文。

查看日志

git log

# 额外包含被操作的文件名
git log --stat

# 简要日志,只包含提交版本号和注释标题
git log --pretty=oneline

# 只包含指定文件的提交版本号和注释标题
git log --pretty=oneline '文件名'

# 包含了所有操作内容【不建议使用】
git log -p

# 查看提交版本号
git reflog

# 图表结构显示所有分支提交记录
git log --oneline --graph --all

撤销操作

重新提交

git commit --amend

这个命令会将暂存区中的文件提交。 如果自上次提交以来你还未做任何修改(例如,在上次提交后马上执行了此命令), 那么快照会保持不变,而你所修改的只是提交信息。

取消暂存的文件

git reset head '文件名'

撤销对文件的修改【危险】

git checkout '文件名'

撤销提交操作

# 回退到上一次提交时
git reset --hard HEAD^

# 回退到第n次操作前
git reset --hard HEAD~n

# 回退到指定版本号
git reset --hard 版本号

Git 分支

几乎所有的版本控制系统都以某种形式支持分支。使用分支意味着你可以把你的工作从开发主线上分离开来,以免影响开发主线。 在很多版本控制系统中,这是一个略微低效的过程——常常需要完全创建一个源代码目录的副本。对于大项目来说,这样的过程会耗费很多时间。

有人把 Git 的分支模型称为它的“必杀技特性”,也正因为这一特性,使得 Git 从众多版本控制系统中脱颖而出。 为何 Git 的分支模型如此出众呢? Git 处理分支的方式可谓是难以置信的轻量,创建新分支这一操作几乎能在瞬间完成,并且在不同分支之间的切换操作也是一样便捷。 与许多其它版本控制系统不同,Git 鼓励在工作流程中频繁地使用分支与合并,哪怕一天之内进行许多次。 理解和精通这一特性,你便会意识到 Git 是如此的强大而又独特,并且从此真正改变你的开发方式。

概述

Git 保存的不是文件的变化或者差异,而是一系列不同时刻的快照。

在进行提交操作时,Git 会保存一个提交对象(commit object)。知道了 Git 保存数据的方式,我们可以很自然的想到——该提交对象会包含一个指向暂存内容快照的指针。但不仅仅是这样,该提交对象还包含了作者的姓名和邮箱、提交时输入的信息以及指向它的父对象的指针。首次提交产生的提交对象没有父对象,普通提交操作产生的提交对象有一个父对象,而由多个分支合并产生的提交对象有多个父对象。

Git 的分支,其实本质上仅仅是指向提交对象的可变指针。Git 的默认分支名字是 master。在多次提交操作之后,你其实已经有一个指向最后那个提交对象的 master 分支。master 分支会在每次提交时自动向前移动。

创建分支

git branch '分支名'

切换分支

git checkout '分支名'

创建并切换分支

git checkout –b '分支名'

查看分支

# 查看所有分支
git branch

# 额外加上最后一次提交
git branch -v

分支小总结

Git 与过去大多数版本控制系统形成了鲜明的对比,它们在创建分支时,将所有的项目文件都复制一遍,并保存到一个特定的目录。完成这样繁琐的过程通常需要好几秒钟,有时甚至需要好几分钟。所需时间的长短,完全取决于项目的规模。而在 Git 中,任何规模的项目都能在瞬间创建新分支。同时,由于每次提交都会记录父对象,所以寻找恰当的合并基础(译注:即共同祖先)也是同样的简单和高效。这些高效的特性使得 Git 鼓励开发人员频繁地创建和使用分支。

合并分支

git merge '分支名'

删除分支

git branch -d '分支名'

合并冲突【重点】

有时候合并操作不会如此顺利。如果你在两个不同的分支中,对同一个文件的同一个部分进行了不同的修改,Git 就没法干净的合并它们。

Git 变基

git rebase 分支名

Git 保存恢复

保存进度

# 将未提交的内容暂存在栈中
git stash

# 在上面的基础上添加注释
git stash save 注释

查看栈中的内容

git stash list

恢复进度

# 将当前stash中的内容弹出,并应用到当前分支对应的工作目录上
git stash pop

注意,栈的特点是先进后出,所以这里使用的是pop命令。

应用栈

# 将栈中的内容应用到当前目录,该命令不会将内容从堆栈中删除
git stash apply

清空栈

git stash clear

从最新的 stash 中创建分支

git stash branch

远程仓库的使用

远程仓库是指托管在因特网或其他网络中的你的项目的版本库。你可以有好几个远程仓库,通常有些仓库对你只读,有些则可以读写。 与他人协作涉及管理远程仓库以及根据需要推送或拉取数据。 管理远程仓库包括了解如何添加远程仓库、移除无效的远程仓库、管理不同的远程分支并定义它们是否被跟踪等等。

【注意】远程仓库可以在你的本地主机上。你完全可以在一个“远程”仓库上工作,而实际上它在你本地的主机上。 词语“远程”未必表示仓库在网络或互联网上的其它位置,而只是表示它在别处。 在这样的远程仓库上工作,仍然需要和其它远程仓库上一样的标准推送、拉取和抓取操作。

克隆远程仓库

为了得一个项目的拷贝,我们需要知道这个项目仓库的地址。Git 能在许多协议下使用,所以地址可能以 ssh://http(s)://git://,或是只是以一个用户名(git 会认为这是一个 ssh 地址)为前辍。有些仓库可以通过不只一种协议来访问,例如,Git 本身的源代码你既可以用 git:// 协议来访问:

git clone git://git.kernel.org/pub/scm/git/git.git

也可以通过 http 协议来访问:

git clone http://www.kernel.org/pub/scm/git/git.git

由此可见,克隆一个项目的指令为:

git clone '路径'

查看远程仓库

git remote

# 显示远程仓库地址
git remote -v

添加远程仓库

git remote add 名称 路径

从远程仓库中抓取

# 抓取指定URL路径中的所有内容
git fetch 路径

# 会抓取克隆(或上一次抓取)后新推送的所有内容
git fetch origin

这个命令会访问远程仓库,从中拉取所有你还没有的数据。执行完成后,你将会拥有那个远程仓库中所有分支的引用,可以随时合并或查看。

从远程仓库中拉取

# 将fetch抓取的内容拉到分支中
git pull

# 拉取指定路径中的内容
git pull origin

# 拉取指定路径,指定分支中的内容
git pull origin master

推送到远程仓库

git push 路径 分支名

GitHub

GitHub 是最大的 Git 版本库托管商,是成千上万的开发者和项目能够合作进行的中心。大部分 Git 版本库都托管在 GitHub,很多开源项目使用 GitHub 实现 Git 托管、问题追踪、代码审查以及其它事情。所以,尽管这不是 Git 开源项目的直接部分,但如果想要专业地使用 Git,你将不可避免地与 GitHub 打交道,所以这依然是一个绝好的学习机会。

注册账号

创建仓库

生成个人访问令牌

成为合作伙伴

Idea 操作 Git

关联 Git

关联 GitHub

克隆远程仓库

第一种,通过其他工具(如:Git Bash)将Git项目克隆到本地,然后使用IDEA直接打开项目。File --> Open...

第二种,使用IDEA从版本库直接导入项目。

创建本地仓库

不要忘记添加忽略文件。

添加文件到暂存区

已存在文件

新建文件

创建文件时会提醒是否每次新建文件都添加到暂存区,可以选择不再询问,这样所有文件创建时都会自动添加到暂存区中,并且所有文件只需要添加一次即可。

忽略文件

提交代码

推送到远程仓库

从远程仓库拉取

创建分支

切换分支

删除分支

合并分支

合并冲突处理

回退提交

  1. Reset Type

    1. Mixed是默认方式。只保留源码,会回退本地仓库和暂存区的信息。

    2. Soft 回退到某个版本。回退到暂存区。如果还要提交,直接 commit。

    3. Hard 彻底回退,本地源码也会变成上一个提交版本的内容,不保留未提交的代码。

  2. To Commit

    表示回滚到哪个版本,例如,HEAD 为当前版本,HEAD^ 为上一个版本;

变基

本地分支同步到远程仓库

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值