说明
在大型项目开发或者多人协作开发时,都希望可以对软件代码进行管理和追踪,以便确认开发的进度和方便问题追溯。这就需要使用到版本控制系统(VCS),比如Git就是一款很优秀的版本控制工具。如今很多项目都在使用Git进行版本控制,这也是该类工具发展到现在的结果。
除了VCS,这类工具可能还有其它的名字,如源代码管理器(SCM),修订控制系统(RCS)等。当然该类工具也不止Git一种,另外还有BitKeeper,SVN等。如果之前没有接触过其它工具的话,可以在直接使用Git进行代码管理。
重要的是,Git是开源的。
安装
Git支持在Linux,Windows等系统上使用,只是可能安装过程有所区别。
Linux/Ubuntu
在Ubuntu系统种,Git是很多包的集合,并且每个包都可以根据需要进行独立安装:
- git-arch:可以将项目从Arch转变为Git,或者对Git进行转换
- git-cvs:可以将项目从CVS转变为Git,或者对Git进行转换
- git-svn:可以将项目从SVN转变为Git,或者对Git进行转换
- git-gui:是Git的一种基于Tcl/Tk的图形用户界面
- gitk:是Tcl/Tk编写的侧重项目历史可视化的Git浏览器
- gitweb:使用Perl编写的,可以在浏览器中显示Git版本库
- git-email:可以通过电子邮件发送Git补丁
- git-daemon-run:版本库共享,该包建立了守护进程服务,以便通过接收匿名下载请求的方式来共享版本库
- git-doc:用户手册
而安装可以直接通过如下方式安装:
sudo apt-get install git git-doc gitweb git-gui gitk git-email git-svn
源码
源码目录为:
https://github.com/git/git
如果只是使用的话,直接安装应该就足够使用了。
Windows
msysGit可以直接通过安装包进行安装,该安装包已经包含了所有的依赖关系。
https://gitforwindows.org/
基本操作
git命令行
git操作简单,可以直接在命令行输入命令:
$ git
usage: 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>]
[--super-prefix=<path>] [--config-env=<name>=<envvar>]
<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 help --all
See 'git help <command>' to read about a specific subcommand
Main Porcelain Commands
add Add file contents to the index
am Apply a series of patches from a mailbox
archive Create an archive of files from a named tree
bisect Use binary search to find the commit that introduced a bug
branch List, create, or delete branches
bundle Move objects and refs by archive
checkout Switch branches or restore working tree files
cherry-pick Apply the changes introduced by some existing commits
citool Graphical alternative to git-commit
clean Remove untracked files from the working tree
clone Clone a repository into a new directory
commit Record changes to the repository
describe Give an object a human readable name based on an available ref
diff Show changes between commits, commit and working tree, etc
fetch Download objects and refs from another repository
format-patch Prepare patches for e-mail submission
gc Cleanup unnecessary files and optimize the local repository
gitk The Git repository browser
grep Print lines matching a pattern
gui A portable graphical interface to Git
init Create an empty Git repository or reinitialize an existing one
log Show commit logs
maintenance Run tasks to optimize Git repository data
merge Join two or more development histories together
mv Move or rename a file, a directory, or a symlink
notes Add or inspect object notes
pull Fetch from and integrate with another repository or a local branch
push Update remote refs along with associated objects
range-diff Compare two commit ranges (e.g. two versions of a branch)
rebase Reapply commits on top of another base tip
reset Reset current HEAD to the specified state
restore Restore working tree files
revert Revert some existing commits
rm Remove files from the working tree and from the index
shortlog Summarize 'git log' output
show Show various types of objects
sparse-checkout Initialize and modify the sparse-checkout
stash Stash the changes in a dirty working directory away
status Show the working tree status
submodule Initialize, update or inspect submodules
switch Switch branches
tag Create, list, delete or verify a tag object signed with GPG
worktree Manage multiple working trees
git help --all对git中的子命令进行了分类,而通常用户也用不到所有的命令,因此有侧重的了解学习即可。下面再看几个常用的命令。
创建初始版本库
在任一目录下执行该命令都会创建初始版本库,甚至是空目录都可以。
$ git init
上述命令执行完后,会在当前目录生成.git文件夹,.git在Ubuntu系统中表示隐藏目录。Git会将包含.git的当前目录作为项目的工作目录,而Git则会维护隐藏在.git中的版本库。
添加文件到版本库
开发过程中,必然设计到文件的增删改,其中可以使用如下命令添加文件到版本库:
$ git add memo.txt
这里先新建了memo.txt文件,然后使用上述命令添加该文件到版本库,这里再使用git status看一下文件添加前后的状态对比。
添加前:
$ git status
On branch master
No commits yet
Untracked files:
(use "git add <file>..." to include in what will be committed)
memo.txt
nothing added to commit but untracked files present (use "git add" to track)
添加后:
$ git status
On branch master
No commits yet
Changes to be committed:
(use "git rm --cached <file>..." to unstage)
new file: memo.txt
添加前后的状态不同,说明添加文件的操作引起了状态的变化,从上边的注释也可以看出是将memo.txt添加到了版本库,进行了追踪,而文件添加之后才可以进行提交。
查看版本库状态
这个很简单,之前也提到过:
git status
上面的命令会将版本库和当前工作区进行对比,打印有差异的部分,显示中间状态。简而言之,就是查看状态。
提交
之前只是将文件添加到版本库中建立了追踪,而若该文件核准无误,就可以提交了。
$ git commit -m "Commit memo.txt"
[master (root-commit) d4fe8e9] Commit memo.txt
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 memo.txt
提交后的状态为:
$ git status
On branch master
nothing to commit, working tree clean
提交后显示改变了一个文件,并且工作目录是干净的,这表示工作目录中不包含任何与版本库中不同的未知或者更改过的文件。
再看提交的格式中存在-m参数,这是因为Git要求再每次提交时记录其日志信息作为注释,以增强可读性,方便理解和问题追溯。
同时也可以设置交互式的提交方式,这样可以通过交互式的方式进行提交日志编写,增加灵活度:
$ export GIT_EDITOR=vim
这样可以在vim中编写提交命令中-m的参数,更灵活。
配置提交作者
之前的提交操作中,能够正确提交是因为在初始化版本库之前就进行了相关配置,因此才没有奇怪的提示。
在正常的开发过程中,需要为项目配置开发人员,并为不同的开发人员设定不同的权限,这就需要在开发之前进行基本配置。最基本的就是名字和email:
git config user.name "abc"
git config user.email "abc@abc.com"
当然也可以直接使用GIT_AUTHOR_NAME和GIT_AUTHOR_EMAIL环境变量来设定名字和email地址,但这些变量一旦设置就会覆盖所有的配置设置。
再次提交
对上面的memo.txt修改后直接执行:
$ git commit memo.txt -m "Modify memo.txt"
该命令会将修改直接提交到版本库,而不用执行git add命令,这也是合理的,在之前已经使用git add添加了该文件,并对该文件进行了追踪,因此后续的修改便可以直接提交。
但是如果未指明文件的话,仍然需要进行git add操作。
查看提交
如果在某个时间下,想要查看存不存在某个提交,或者查看下某个bug有没有修复,可能需要查看提交:
$ git log
commit 59bef55119aa8d47986ecb59f5ff6f34beef1d6c (HEAD -> master)
Author: wood_glb <wood_glb@git.com>
Date: Sat Jun 18 10:08:45 2022 +0800
Modify memo.txt
commit 69d01502f44167375feb6430783aef8685aadc57
Author: wood_glb <wood_glb@git.com>
Date: Sat Jun 18 10:05:36 2022 +0800
Commit memo.txt
这样就显示了两次提交,其中每次提交包含提交索引,提交作者,提交日期,提交日志,还说明了当前HEAD所在的位置。
而如果需要查看某个特定的提交:
$ git show 59bef55119aa8d47986ecb59f5ff6f34beef1d6c
commit 59bef55119aa8d47986ecb59f5ff6f34beef1d6c (HEAD -> master)
Author: wood_glb <wood_glb@git.com>
Date: Sat Jun 18 10:08:45 2022 +0800
Modify memo.txt
diff --git a/memo.txt b/memo.txt
index e69de29..8baef1b 100644
--- a/memo.txt
+++ b/memo.txt
@@ -0,0 +1 @@
+abc
使用该命令便可以看到特定提交的具体修改内容。
上面的命令也可以简短写,一般提交码经过特殊计算,很少有重复:
$ git show 59bef5
commit 59bef55119aa8d47986ecb59f5ff6f34beef1d6c (HEAD -> master)
Author: wood_glb <wood_glb@git.com>
Date: Sat Jun 18 10:08:45 2022 +0800
Modify memo.txt
diff --git a/memo.txt b/memo.txt
index e69de29..8baef1b 100644
--- a/memo.txt
+++ b/memo.txt
@@ -0,0 +1 @@
+abc
而若git show没有指明某次提交,则是最近的一次提交:
$ git show
commit 59bef55119aa8d47986ecb59f5ff6f34beef1d6c (HEAD -> master)
Author: wood_glb <wood_glb@git.com>
Date: Sat Jun 18 10:08:45 2022 +0800
Modify memo.txt
diff --git a/memo.txt b/memo.txt
index e69de29..8baef1b 100644
--- a/memo.txt
+++ b/memo.txt
@@ -0,0 +1 @@
+abc
可见,打印结果都是一致的。
也可以使用如下的查看命令:
$ git show-branch --more=10
[master] Modify memo.txt
[master^] Commit memo.txt
该命令可以查看当前开发分支的单行摘要。
查看提交差异
提交差异可以通过git diff进行查看,比如比较两次提交间的差异:
$ git diff 59bef55119aa8d47986ecb59f5ff6f34beef1d6c 69d01502f44167375feb6430783aef8685aadc57
diff --git a/memo.txt b/memo.txt
index 8baef1b..e69de29 100644
--- a/memo.txt
+++ b/memo.txt
@@ -1 +0,0 @@
-abc
或者是:
$ git diff 59bef5 69d015
diff --git a/memo.txt b/memo.txt
index 8baef1b..e69de29 100644
--- a/memo.txt
+++ b/memo.txt
@@ -1 +0,0 @@
-abc
上面的命令显示了两次提交中版本库的差异。
文件删除
从版本库中删除一个文件可以执行:
$ git rm memo.txt
rm 'memo.txt'
此时查看下状态:
$ git status
On branch master
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
deleted: memo.txt
可以看出,此时文件并没有真正删除,具体的删除仍然需要提交后才会生效:
$ git commit -m "Remove memo.txt"
[master 1db3bed] Remove memo.txt
1 file changed, 1 deletion(-)
delete mode 100644 memo.txt
此时才算是真正的删除了。
文件重命名
这里再次新建memo.txt并提交,然后执行:
$ git mv memo.txt doc.txt
此时的状态为:
$ git status
On branch master
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
renamed: memo.txt -> doc.txt
说明该操作仍然需要提交才会生效:
$ git commit -m "Rename memo.txt to doc.txt"
[master 77b0efa] Rename memo.txt to doc.txt
1 file changed, 0 insertions(+), 0 deletions(-)
rename memo.txt => doc.txt (100%)
创建版本库副本
实际开发中,用户可能需要从服务器上拉取项目,也就是在本地创建版本库的副本,此时需要使用git clone命令:
$ git clone GIT GIT_COPY
Cloning into 'GIT_COPY'...
done.
现在这两个版本库包含相同的对象,文件和目录,但还是存在一些不同的,可以使用下述命令查看:
$ ls -lsa GIT GIT_COPY
$ diff -r GIT GIT_COPY
从显示的内容来看,两个库的文件目录不同,某些文件中的内容也是有区别的。
配置文件
Git的配置文件都是.ini文件风格的文本文件。同时Git支持不同层次的配置文件,按照优先级递减的顺序为:
- .git/config:版本库特定的配置设置,可用--file选项修改,是默认选项,这些设置具有最高优先级。
- ~/.gitconfig:用户特定的配置设置,可用--global选项修改
- /etc/gitconfig:系统范围的配置权限,如果有写权限,就可以使用--system选项修改。这些设置的优先级最低,根据实际安装位置,该文件也可能在其它位置,或不存在。
比如之前使用了如下命令配置了提交作者:
git config user.name "abc"
git config user.email "abc@abc.com"
上面的配置就是对于针对该版本库设置的名字和email地址,该配置会覆盖--global设置,并且在--global缺省状态下就是版本库配置。
而如果使用--global指定了某项设置:
git config --golbal user.name "abc"
git config --golbal user.email "abc@abc.com"
就可以使用上述配置对所有版本库进行提交,而上面的配置实际上是对~/.gitconfig文件中的user.name和user.email属性赋值。
可以通过下述命令列出在整组配置文件中所有变量及其设置值:
$ git config -l
而同样如果需要去除掉某项设置,则可以使用git config中的--unset选项:
git config --unset --global user.name
配置别名
在Linux系统中,用户可以为系统命令设置别名,以满足用户的开发习惯和灵活性。而Git也提供了配置别名,以方便命令的使用。
$ git config --global alias.show-log "show-branch --more=10"
$ git show-log
上面的命令中创建了show-log别名,以等效于show-branch --more=10的使用,这样会更灵活方便。
之后若不需要该别名,可以使用--unset选项来移除该设置。