如果你知道Linux那你一定知道Linus Torvalds,Git正是这位传奇天才的第二个杰作。关于Git,有人说是Linus为了开发Linux Kernel的兄弟们不被人拿捏。事情发生在2005年4月,Andrew Tridgell 为了开发一个可以与BitKeeper交互的工具,试图反编译BitKeeper。这让开发该软件的公司BitMover得知并取消了Linux社区免费试用BitKeeper的权利。这也成为了Linus开发Git的契机,促进了Git这一伟大作品的诞生。关于Git的全部使用方法大概可以写好几本书了,这里仅就环境的配置以及基本的使用做一些记录,剩下的使用可以参考官方文档。
同生活中的许多伟大事物一样,Git诞生于一个极富纷争大举创新的年代。Linux内核开源项目有着为数众多的参与者。 绝大多数的Linux内核维护工作都花在了提交补丁和保存归档的繁琐事务上(1991-2002年间)。到2002年,整个项目组开始启用一个专有的分布式版本控制系统BitKeeper来管理和维护代码。到了2005年,开发BitKeeper的商业公司同Linux内核开源社区的合作关系结束,他们收回了Linux内核社区免费使用BitKeeper的权力。 这就迫使Linux开源社区(特别是Linux的缔造者Linus Torvalds)基于使用BitKeeper 时的经验教训,开发出自己的版本系统。他们对新的系统制订了若干目标:
自诞生于2005年以来,Git日臻成熟完善,在高度易用的同时,仍然保留着初期设定的目标。 它的速度飞快,极其适合管理大项目,有着令人难以置信的非线性分支管理系统(参见Git分支)。
那么,简单地说,Git究竟是怎样的一个系统呢? 请注意接下来的内容非常重要,若你理解了 Git 的思想和基本工作原理,用起来就会知其所以然,游刃有余。 在学习 Git 时,请尽量理清你对其它版本管理系统已有的认识,如 CVS、Subversion 或 Perforce, 这样能帮助你使用工具时避免发生混淆。尽管 Git 用起来与其它的版本控制系统非常相似, 但它在对信息的存储和认知方式上却有很大差异,理解这些差异将有助于避免使用中的困惑。
直接记录快照,而非差异比较
Git和其它版本控制系统(包括Subversion和近似工具)的主要差别在于Git对待数据的方式。从概念上来说,其它大部分系统以文件变更列表的方式存储信息,这类系统(CVS、Subversion、Perforce、Bazaar等等) 将它们存储的信息看作是一组基本文件和每个文件随时间逐步累积的差异——它们通常称作 基于差异[delta-based]的版本控制。
再进一步记录git的使用方法之前,首先需要配置一个可用的最小化环境。以Windows和Linux平台为例,这两个平台配置方法几乎完全一样,只是在配置路径的时候稍有差别。
apt install git
git config --global user.name 'xxx'
git config --global user.email 'xxx@yyy'
git config --global core.sshCommand "ssh -i 'path/to/your/key'"
Host github.com HostName github.com User mffan0922 IdentityFile path/to/your/key AddKeysToAgent yes PreferredAuthentications publickey Port 22
另外涉及到多个平台配置,或者多用户配置的时候,一般不使用--global
选项,而是在对应项目下使用--local
选项,设定用户名和邮箱,设定之前需要使用--unset
删除全局配置。其实不删除也可以,因为--local
的优先级比--global
的优先级高。
Git是由三个(如果包括远程仓库,那就是四个)区域组成,分别是工作区,暂存区和本地仓库,对应的状态有(un)tracked/modified/staged/committed,Git更像是把数据看作是对小型文件系统的一系列快照。在Git中,每当你提交更新或保存项目状态时,它基本上就会对当时的全部文件创建一个快照并保存这个快照的索引。为了效率,如果文件没有修改,Git不再重新存储该文件,而是只保留一个链接指向之前存储的文件。Git对待数据更像是一个快照流。
git
命令支持的选项非常之多,对应于研发人员的各种需求;一般使用者不需要了解这么多,只要掌握基础的用法就足够了。如果想了解更多命令的详细用法,可以使用git cmd --help
的方式来获取,cmd
代表git
支持的各种子命令。另外git
也非常贴心,再执行每一步的时候都会给出近乎于啰嗦的指导。使用git --help
会输出如下简要的帮助信息:
bashusage: git [--version] [--help] [-C <path>] [-c <name>=<value>]
[--exec-path[=<path>]] [--html-path] [--man-path] [--info-path]
[-p | --paginate | -P | --no-pager] [--no-replace-objects] [--bare]
[--git-dir=<path>] [--work-tree=<path>] [--namespace=<name>]
<command> [<args>]
These are common Git commands used in various situations:
start a working area (see also: git help tutorial)
clone Clone a repository into a new directory
init Create an empty Git repository or reinitialize an existing one
work on the current change (see also: git help everyday)
add Add file contents to the index
mv Move or rename a file, a directory, or a symlink
restore Restore working tree files
rm Remove files from the working tree and from the index
sparse-checkout Initialize and modify the sparse-checkout
examine the history and state (see also: git help revisions)
bisect Use binary search to find the commit that introduced a bug
diff Show changes between commits, commit and working tree, etc
grep Print lines matching a pattern
log Show commit logs
show Show various types of objects
status Show the working tree status
grow, mark and tweak your common history
branch List, create, or delete branches
commit Record changes to the repository
merge Join two or more development histories together
rebase Reapply commits on top of another base tip
reset Reset current HEAD to the specified state
switch Switch branches
tag Create, list, delete or verify a tag object signed with GPG
collaborate (see also: git help workflows)
fetch Download objects and refs from another repository
pull Fetch from and integrate with another repository or a local branch
push Update remote refs along with associated objects
'git help -a' and 'git help -g' list available subcommands and some
concept guides. See 'git help <command>' or 'git help <concept>'
to read about a specific subcommand or concept.
See 'git help git' for an overview of the system.
这里采用解决问题的方式来记录,使用git
的基本命令,但是单纯的记录每个命令的用法,因为该命令的子命令太多了,在使用场景下会更容易理解其原理,掌握了基础用法之后,在遇到其他问题时,也可以很自然的扩充。
Git安装好之后,需要使用git config
命令来做一些基本的配置,其中包括让Git正常运行的用户名和邮箱配置。
bashgit config --global user.name "[firstname lastname]" # 设置全局用户
git config --global user.email "[valid-email]" # 设置对应邮箱
config命令支持system/global/local三种层级,系统级是针对服务器所有用户生效,配置文件一般记录在/etc/gitconfig
文件;全局配置是针对当前用户所有仓库生效,一般记录在/userDir/.gitconfig
文件;而本地级则只对当前文件夹对应的仓库生效,一般记录在.git/config
文件,三者的优先级是依次升高的,。该命令其他常用用法汇总如下:
bashgit config --list # 列出当前repo的配置
git config --global --list # 列出全局repo的配置
git config --global color.ui auto # 设置git彩色输出
git config --global core.editor vim # 设置默认编辑器
git config --global --unset user.name # 删除global层级的user.name配置
git config --global init.defaultBranch main # 将默认分支名称修改为main
这里有两种情景,一种是创建一个空的Git仓库,另一种是已经有了个项目,现在要将其纳入Git管理:
创建空仓库
bash# Method One ==========================
mkdir git_learning
cd git_learning
git init
# Method Two ==========================
git init git_learning
管理已有项目
bashcd project
git init
git add -A
git commit -m '[add] initial commit'
git add
命令是Git最常用的命令之一,其作用是将文件从工作区转移到暂存区,以等待后续提交到仓库,如下是该命令的其他常用参数:
bashgit add -u # 将已纳入管理且已修改的文件,放置到暂存区
git add -A # 将所有已修改文件,包括untracked文件,全部放置到暂存区
git add -f fileA # 将fileA(即使已经被忽略)放置到暂存区
clone
指令是从远程将仓库下载(克隆)下来,一般情况默认将仓库所有的信息都会下载下来。执行完git clone
命令后,当前目前称为目录A,目录A下 并没有形成本地仓库,命令执行结束之后,目录A下会多一个目录B,目录B下就是本地git仓库,并且本地git仓库已经和远程git仓库连接。此时,本地仓库默认分支名字是main,因为当前远程仓库的默认分支名字是main。本地仓库关联的远程仓库当前默认名字是origin。
bashgit clone git@github.com:manerfan/vuesume.git # 使用ssh协议从远程clone下来,需要配置密钥
git clone https://github.com/manerfan/vuesume.git # 使用https协议冲远程clone下来
git clone https://github.com/manerfan/vuesume.git rename-to-git # 将克隆的仓库下载到本地,并重命名为rename-to-git
git clone -b dev https://github.com/manerfan/vuesume.git # 自动将dev分支配置为本地分支
git clone --bare git@github.com:manerfan/vuesume.git # 创建一个裸仓库,后续需要手动checkout
理想的情况下是在远程创建好仓库,使用git clone
命令下载到本地,然后在本地添加新的项目文件,并push
到远程,这种情况下基本不会出现什么问题;还有一种情况是本地已经有项目文件了,这时就需要手动关联本地和远程仓库,必要的话手动解决文件冲突,并提交到远程。
bashcd local_prj
git init
git add -A
git commit -m '[add] initial commit'
git remote add origin git@github.com:manerfan/vuesume.git
git pull origin main --allow-unrelated-histories
# 手动解决冲突
git push -u origin main
几乎每一种版本控制系统都以某种形式支持分支,一个分支代表一条独立的开发线。使用分支意味着你可以从开发主线上分离开来,然后在不影响主线的同时继续工作。Git 分支实际上是指向更改快照的指针。有人把Git的分支模型称为必杀技特性,而正是因为它,将Git从版本控制系统家族里区分出来。
bashgit branch -av # 查看所有分支
git branch new-branch # 基于当前分支,新建分支
git checkout new-branch # 切换到新分支
git checkout -b new-branch # 基于当前分支,新建分支,并切换到新分支
git branch -d deleted-branch # 将分支删除
git push origin --delete deleted-branch # 将远程分支删除
git merge dev # 将dev分支,合并到当前分支
git branch --set-upstream-to=origin/main # 将当前分支设定跟踪远程分支
所谓Git三部曲,指的是从添加一个文件,纳入到Git管理,放置到暂存区,提交到本地仓库,最后同步到远程仓库的过程。
bashgit add * # 添加所有文件,包括未跟踪和已修改,但不包括隐藏文件
git add -A # 添加所有文件,包括未跟踪和已修改和隐藏文件
git add . # 同 git add -A
git commit -m '[add/modify] something to say' # 提交到本地仓库,并添加注释
git commit -a -m '[add/modify] something to say' # 将所有已变更文件,提交到本地仓库,并添加注释
git commit --amend -m '[add/modify] something to say' # 对于同一个文件,多次修改后提交,生成一个commit id
git push origin main # 推送到远程
至于如何撤销变更,以及提交等,在操作Git的时候,会给出相应的提示,再有比较进阶的用法,例如如何变更已经提交的内容,如何整理已经提交的commit id,甚至合并分支时需要注意的事项等等,后续用到的时候在做补充。
本文作者:Manford Fan
本文链接:
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!