[TOC]
摘要
版本控制工具的历史
版本控制工具的起源:diff与patch
- diff
- 用于比较两个文件或者目录之间的差异
- 例如命令:
diff -u left.c right.c
,left.c是原始文件,right.c是目标文件 -
代表原始文件,+
代表目标文件
- patch
- patch是diff的反向操作
- 把diff的结果保存到文件中后,就可以通过diff文件在原始文件中推断目标文件,或者从目标文件中还原原始文件
patch left.c diff.txt
或者反向操作,patch -R right.c diff.c
- RCS
- 最早期的本地版本控制工具
- 通过对diff和patch的集合来完成
- 问题是RCS只适合本地版本控制,不适合多人提交
- CVS&SVN
- 集中式版本控制工具
- CVS:不支持原子化提交,会导致客户端向服务器端提交不完整数据,网络传输效率低。
- CVN目的是创建一个更好用的版本控制系统
- CVN的问题:查看日志、提交数据等操作需要与服务器交互。
- 集中式版本控制出现的问题:
- 狭窄的提交通道
- 数据安全问题
- git
- 记录快照的版本控制
- git把数据看做是小型文件系统的一组快照
- 每次提交更新,或者在git中保存项目状态时,git会对当时的全部文件制作一个快照,并保存快照索引。
- 其他版本控制系统则是将保存的信息看做是一组基本文件和每个文件随着时间逐步累积的差异
- 分布式的版本控制
- 记录快照的版本控制
git基本命令
基本配置
配置个人身份
git config --global user.name "xnchen"
git config --global user.email xnchen19@gmail.com
换行符配置
windows换行符是CRLF,两个字符。Mac和Linux只有一个字符LF。
windows系统上,使用core.autocrlf来在提交时自动地把结束符CRLF转换为LF,在签出(pull的意思吗?)代码时把LF转换成CRLF
$ git config --global core.autocrlf true
在Mac或者Linux系统上,使用core.autocrlf来在input的时候把CRLF转换成LF,在签出时不转换:
$ git config --global core.autocrlf input
编码格式配置
# 中文编码支持
git config --config gui.encoding utf-8
git config --config i18n.commitencoding utf-8
git config --config i18n.logoutputencoding utf-8
# 显示路径中的中文
git config --global core.quotepath false
与服务器的认证配置方式
- http/https协议认证
- ssh协议认证
基本概念
工作区域
-
版本库(repository)
在工作目录下的.git目录下。存放了git用来管理工程的所有版本数据,也可以叫本地仓库。
-
工作区(working directory)
日常工作的代码文件所在文件夹
-
暂存区(stage)
在.git/index文件夹中
文件状态
-
已修改(modified)
修改的文件,还未提交保存
-
已暂存(staged)
把已修改文件放在下次提交时要保存的清单中
-
已提交(commited)
文件修改已经被安全保存到本地数据库
基本命令
工程准备
git init project_name # 在当前目录下创建新的工作文件夹,并在里面创建了.git文件夹
git init # 在本目录中创建.git文件夹
git clone [URL]
git lfs clone [URL]
# 如果所在项目git服务器支持git-lfs,则它对二进制文件进行区别管理,克隆工程时请使用git lfs clone
# 否则克隆操作无法下载工程中的二进制文件,工程内容不完整
# (问明白git托管仓库的管理员)
新增/删除/移动文件到暂存区
git add [文件名]
# 将新创建文件加入到暂存区
git rm [文件名]
# 将文件从当前分支的缓存区删除,因此它将从当前分支的下一个提交快照中被删除,该文件再之后的节点中不再受git工程的挂历
# 你也可以直接在硬盘上删除文件,然后对该文件执行git commit,git会自动将删除的文件从索引中删除,效果一样
git mv [文件名] [目标目录] # 可以移动文件,可以用于重命名文件
查看工作区
git diff --cached # 当前索引和上次提交之间的差异
git diff [节点名1] [节点名2] # 比较节点之间的差异
git diff --cached --name-status # 加--name-status参数,只看文件列表
# M:modifed
# A:added
# D:Delete
git status # 用于显示工作目录和暂存区状态
提交更改的文件
# 将暂存区的文件改动提交到本地的版本库
git commit [file_name] -m "commit message"
# 批量提交暂存区所有文件到本地版本库
git commit -am "commit message"
# git commit弹出的文件第一行是commit说明的标题,之后是详细说明。格式都是markdown
# 修改最近一次提交的信息,会新生成一个节点代码代替上一个节点
git commit --amend
查看日志
git log
# 用于查看提交历史
# 按照提交时间由近到远列出所有历史提交日志
git log --name-status
# 查看提交中的文件操作
git log -1
# 只看最近一次的节点
git reflog
# 查看最近的git命令
推送远端仓库
git push origin [branch_name]
# branch_name决定了本地分支推送到远端服务器上的分支名,其他人可以据此获取该分支上的改动内容
# origin指的是目标服务器名称,默认应该都是origin
git push origin [branch_name]:[new_branch_name] # 本地分支名可以与推送到远端的分支名不同
分支管理
git branch # 查看本地工程的所有git分支名称
git branch -r # 查看远端服务器上拥有的分支
git branch -a # 查看本地和远端的所有分支
# 新建分支
# 根据当前分支节点创建
git branch [分支名称] # 不会切换到新分支
git checkout -b [分支名称] # 切换到新分支
# 删除分支
# 删除本地分支
git branch -d
git branch -D # 强制删除
# 远端服务器分支
git branch -d -r [分支名称] # [分支名称]为本地分支名
git push origin : [分支名称] # 删除后还需要推送到服务器上
git push -f # 强制推送
# 切换分支 / 也叫“检出”
# checkout对象可以是分支,也可以是节点或者节点下文件
git checkout [分支名称]
git checkout -f [分支名称]
# 在当前分支工作区存在修改而未提交的文件,与目的分支内容冲突,会导致checkout切换失败,使用-f强制切换
# 获取远端分支的更新,并且自动合并到本地分支
git pull origin [远端分支]:[本地分支]
git pull origin [远端分支] # 如果远端分支和本地分支相同
# 获取远端分支的更新(不自动合并)
git fetch origin [远端分支]:[本地分支]
git fetch origin [远端分支] # 如果远端分支和本地分支相同
# 分支合并
git merge [branch_name] # 将指定分支与当前分支进行比较,将差异合并到当前分支
git merge [source_branch] [target_branch] # 将source分支合并到目标分支
git rebase [branch_name]
git cherry-pick [节点名] # 将制定节点名的提交转移到当前分支的头部
# 如果合并分支出现冲突Confict:进入冲突文件,修改后add文件、commit文件,即可解决,并自动合并
# 撤销操作
git reset [commit_id] # 工作区回退到历史提交节点 # 谨慎使用,不会给确认机会,之后的提交都会消失
git checkout . # 回退本地所有修改而未提交的内容(用暂存区内容覆盖本地内容) # 谨慎使用,不给任何确认机会
git checkout [filename] # 回退某个文件的未提交改动
git checkout [commit_id]# 回退到历史提交节点
分支的合并
- git merge
-
git rebase
git rebase会造成master主干的重复log,导致log的不清晰,提交时间节点混乱。
git rebase的原则:不要在版本主干上使用rebase。
commit合并
git rebase -i HEAD~n
n是要合并从HEAD开始的n个commit