git基本使用

一、Git简介

Git 是一个免费的、开源的分布式版本控制系统,可以快速高效地处理从小型到大型的各种项目。
Git 易于学习,占地面积小,性能极快。 它具有廉价的本地库,方便的暂存区域和多个工作流分支等特性。其性能优于 Subversion、CVS、Perforce 和 ClearCase 等版本控制工具。

1. 版本控制的三个阶段

版本控制是一种记录文件内容变化,以便将来查阅特定版本修订情况的系统。利用版本控制工具,可以记录文件修改历史记录,从而让用户能够查看历史版本,避免版本混乱,方便版本切换;此外,可以提高团队协作能力和开发效率,大家可以及时获取到最新的代码。

版本控制系统的整个发展可以分为如下三个阶段:

1)本地版本控制系统

许多人习惯用复制整个项目目录的方式来保存不同的版本,或许还会改名加上备份时间以示区别。 这么做唯一的好处就是简单,但是特别容易犯错。 有时候会混淆所在的工作目录,一不小心会写错文件或者覆盖意想外的文件。

为了解决这个问题,人们很久以前就开发了许多种本地版本控制系统,大多都是采用某种简单的数据库来记录文件的历次更新差异。

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

git基本使用_第1张图片

2)集中化的版本控制系统

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

git基本使用_第2张图片

这种做法带来了许多好处,特别是相较于老式的本地 VCS 来说。 现在,每个人都可以在一定程度上看到项目中的其他人正在做些什么。 而管理员也可以轻松掌控每个开发者的权限,并且管理一个 CVCS 要远比在各个客户端上维护本地数据库来得轻松容易。

但这么做也有一个显而易见的缺点,那就是是中央服务器的单点故障。

  • 如果宕机一小时,那么在这一小时内,谁都无法提交更新,也就无法协同工作
  • 如果中心数据库所在的磁盘发生损坏,又没有做恰当备份,毫无疑问你将丢失所有数据——包括项目的整个变更历史,只剩下人们在各自机器上保留的单独快照。

本地版本控制系统也存在类似问题,只要整个项目的历史记录被保存在单一位置,就有丢失所有历史更新记录的风险。

  • CVS

CVS(Concurrent Versions System)诞生于1985年,由荷兰阿姆斯特丹VU大学的Dick Grune教授设计实现。Dick Grune教授和两个学生共同开发一个项目,由于三人工作时间无法协调,急需一个记录和协同开发的软件。于是Dick Grune教授通过脚本语言对RCS(单文件版本管理工具)进行了封装修改,设计出有史以来第一个被大规模使用的版本控制工具CVS。关于这段历史,大佬曾在网站上留下这样的话:

“在1985年的一个糟糕的秋日里,我在校汽车站等车回家,脑海里一直纠结着一件事一如何处理RCS文件、用户文件(工作区)和Entries 文件的复杂关系,有的文件可能会缺失、冲突、删除,等等。我的头有些晕了,于是决定画一个大表,将复杂的关联画在其中,看看出来的结果是什么样的…”

CVS的成功引发了版本控制系统的爆发,各种版本控制系统相继被开发出来,其中比较典型的系统就是SVN(Subversion)。

1986年Dick通过新闻组发布了CVS,1989年Brian Berliner用C语言将CVS进行了重写。

  • Subversion

由于其命令行工具名为svn,因此通常被简称为SVN。由CollabNet公司于2000年资助并开始开发,目的是创建一个更好用的版本控制系统以取代CVS。SVN的前期由CVS做版本管理,到2001年,开始用于自己的版本控制。

3)分布式版本控制系统

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

git基本使用_第3张图片

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

分布式的版本控制系统出现之后,解决了集中式版本控制系统的缺陷:

  • 服务器断网的情况下也可以进行开发(因为版本控制是在本地进行的)

  • 每个客户端保存的也都是整个完整的项目(包含历史记录,更加安全)

2. Git历史

  • Linus在 1991-2002期间一直使用diff + patch + tar方式维护Linux内核代码
  • 2002-2005,BitMover出于人道主义精神,将商业软件BitKeeper授权Linux社区免费使用
  • 开发Samba的作者Andrew Tridgell试图对BitKeeper进行反向工程,以开发一个能与BitKeeper交互的开源工具,导致BitMover收回了授权。
  • 2005年4月3日,Linus开始开发Git
  • 2005年4月6日,项目发布
  • 2005年4月7日,Git就可以作为自身的版本控制工具
  • 2005年4月18日,发布第一个多分支合并
  • 2005年4月29日,Git性能已经达到Linus的预期
  • 2005年6月16日,Linux内核2.6.13发布,此时Git已经在维护Linux的内核源代码
  • 2005年7月26日,Linus功成身退,将Git的维护交给另一个Git的主要贡献者Junio C Hamano,至今。
  • 2008年,当汤姆·普雷斯顿-沃纳(Tom Preston-Werner)、克里斯·万斯特拉斯(Chris Wanstrath)和PJ·海伊特(PJ Hyett)合作完成一个项目,它名字叫Github。

3. 基本使用

1)安装Git

  • 官网: https://git-scm.com/

  • 安装目录使用非中文且没有空格的目录

  • 其他设置

    git基本使用_第4张图片

    git基本使用_第5张图片

git基本使用_第6张图片

git基本使用_第7张图片

git基本使用_第8张图片

git基本使用_第9张图片

git基本使用_第10张图片

git基本使用_第11张图片

git基本使用_第12张图片

git基本使用_第13张图片

git基本使用_第14张图片

2)让我们开始吧

$ git help
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

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 ' or 'git help '
to read about a specific subcommand or concept.
See 'git help git' for an overview of the system.
命令 作用
git config 设置用户签名
git config --global user.name 用户名
git config --global user.email 邮箱
git init 初始化本地库
git status 查看本地库状态
git add 文件名 添加到暂存区
git commit -m "日志信息" 文件名 提交到本地库
git reflog 查看历史记录
git reset --hard 版本号 版本穿梭

(1)设置用户签名

25294@DESKTOP-KPM1TUP MINGW64 ~/Desktop
$ git config --global user.name 'JustRight'

25294@DESKTOP-KPM1TUP MINGW64 ~/Desktop
$ git config --global user.email '[email protected]'

25294@DESKTOP-KPM1TUP MINGW64 ~/Desktop
$ cat ~/.gitconfig
[user]
        name = JustRight
        email = 252940120@qq.com

签名的作用是区分不同操作者身份。用户的签名信息在每一个版本的提交信息中能够看到,以此确认本次提交是谁做的。Git 首次安装必须设置一下用户签名,否则无法提交代码。
注意:这里设置用户签名和将来登录 GitHub(或其他代码托管中心)的账号没有任何关系。

git config还有很多其他的用途,比如可以用来取别名git config --system alias.ci commit

(2)初始化本地库

25294@DESKTOP-KPM1TUP MINGW64 ~/Desktop
$ cd git-demo

25294@DESKTOP-KPM1TUP MINGW64 ~/Desktop/git-demo
$ git init
Initialized empty Git repository in C:/Users/25294/Desktop/git-demo/.git/

25294@DESKTOP-KPM1TUP MINGW64 ~/Desktop/git-demo (master)
$ ls -a
./  ../  .git/
25294@DESKTOP-KPM1TUP MINGW64 ~/Desktop/git-demo (master)
$ tree -a
.
`-- .git
    |-- HEAD
    |-- config
    |-- description
    |-- hooks
    |   |-- applypatch-msg.sample
    |   |-- commit-msg.sample
    |   |-- fsmonitor-watchman.sample
    |   |-- post-update.sample
    |   |-- pre-applypatch.sample
    |   |-- pre-commit.sample
    |   |-- pre-merge-commit.sample
    |   |-- pre-push.sample
    |   |-- pre-rebase.sample
    |   |-- pre-receive.sample
    |   |-- prepare-commit-msg.sample
    |   |-- push-to-checkout.sample
    |   `-- update.sample
    |-- info
    |   `-- exclude
    |-- objects
    |   |-- info
    |   `-- pack
    `-- refs
        |-- heads
        `-- tags

9 directories, 17 files

25294@DESKTOP-KPM1TUP MINGW64 ~/Desktop/git-demo (master)
$ git status
On branch master

No commits yet

nothing to commit (create/copy files and use "git add" to track)

初始化的效果,生成.git目录,它就是Git的版本库

为了查看目录结构,这里安装了tree命令。安装方法

  • 打开进入 Tree for Windows 页面,选择下载 tree-版本-bin.zip 文件下载
  • 将压缩包中bin目录下的tree.exe复制到Git安装目录下的usr\bin目录即可

Git从版本1.65开始,可以在git init命令后面直接输入目录名,自动完成目录 的创建

(3) 新增文件

25294@DESKTOP-KPM1TUP MINGW64 ~/Desktop/git-demo (master)
$ vi hello.py
a = 1
b = 2
print(a + b)

25294@DESKTOP-KPM1TUP MINGW64 ~/Desktop/git-demo (master)
$ git status
On branch master

No commits yet

Untracked files:
  (use "git add ..." to include in what will be committed)
        hello.py

nothing added to commit but untracked files present (use "git add" to track)

添加文件后再查看状态,检测到了未追踪的文件hello.py

(4) 添加暂存区

25294@DESKTOP-KPM1TUP MINGW64 ~/Desktop/git-demo (master)
$ git add hello.py
warning: LF will be replaced by CRLF in hello.py.
The file will have its original line endings in your working directory

25294@DESKTOP-KPM1TUP MINGW64 ~/Desktop/git-demo (master)
$ git status
On branch master

No commits yet

Changes to be committed:
  (use "git rm --cached ..." to unstage)
        new file:   hello.py

(5)提交本地库

25294@DESKTOP-KPM1TUP MINGW64 ~/Desktop/git-demo (master)
$ git commit -m "first commit"  hello.py
warning: LF will be replaced by CRLF in hello.py.
The file will have its original line endings in your working directory
[master (root-commit) be08904] first commit
 1 file changed, 3 insertions(+)
 create mode 100644 hello.py

25294@DESKTOP-KPM1TUP MINGW64 ~/Desktop/git-demo (master)
$ git status
On branch master
nothing to commit, working tree clean


注意,Git提交时,一定要添加提交说明。

(6)修改文件

25294@DESKTOP-KPM1TUP MINGW64 ~/Desktop/git-demo (master)
$ vi hello.py
a = int(input('please input the first number>'))
b = int(input('please input the second number>'))
print(a+b)

25294@DESKTOP-KPM1TUP MINGW64 ~/Desktop/git-demo (master)
$ git status
On branch master
Changes not staged for commit:
  (use "git add ..." to update what will be committed)
  (use "git restore ..." to discard changes in working directory)
        modified:   hello.py

no changes added to commit (use "git add" and/or "git commit -a")

25294@DESKTOP-KPM1TUP MINGW64 ~/Desktop/git-demo (master)
$ git add hello.py
warning: LF will be replaced by CRLF in hello.py.
The file will have its original line endings in your working directory

25294@DESKTOP-KPM1TUP MINGW64 ~/Desktop/git-demo (master)
$ git status
On branch master
Changes to be committed:
  (use "git restore --staged ..." to unstage)
        modified:   hello.py
  
25294@DESKTOP-KPM1TUP MINGW64 ~/Desktop/git-demo (master)
$ git commit -m "second commit" hello.py
warning: LF will be replaced by CRLF in hello.py.
The file will have its original line endings in your working directory
[master b1bbedb] second commit
 1 file changed, 3 insertions(+), 3 deletions(-)
 
25294@DESKTOP-KPM1TUP MINGW64 ~/Desktop/git-demo (master)
$ git status
On branch master
nothing to commit, working tree clean

(7)历史版本

查看版本信息

25294@DESKTOP-KPM1TUP MINGW64 ~/Desktop/git-demo (master)
$ git reflog
b1bbedb (HEAD -> master) HEAD@{0}: commit: second commit
be08904 HEAD@{1}: commit (initial): first commit

25294@DESKTOP-KPM1TUP MINGW64 ~/Desktop/git-demo (master)
$ git log
commit b1bbedba2f67d0e96014c25043a6757010e12863 (HEAD -> master)
Author: JustRight <252940120@qq.com>
Date:   Wed Jun 1 22:46:36 2022 +0800

    second commit

commit be08904691a3c63d19e75f4a0e2d5dded2dd5cc6
Author: JustRight <252940120@qq.com>
Date:   Wed Jun 1 22:38:00 2022 +0800

    first commit

版本穿梭

25294@DESKTOP-KPM1TUP MINGW64 ~/Desktop/git-demo (master)
$ git reset --hard be08904
HEAD is now at be08904 first commit

25294@DESKTOP-KPM1TUP MINGW64 ~/Desktop/git-demo (master)
$ vi hello.py

25294@DESKTOP-KPM1TUP MINGW64 ~/Desktop/git-demo (master)
$ cat hello.py
a = 1
b = 2
print(a + b)

25294@DESKTOP-KPM1TUP MINGW64 ~/Desktop/git-demo (master)
$ git reflog
be08904 (HEAD -> master) HEAD@{0}: reset: moving to be08904
b1bbedb HEAD@{1}: commit: second commit
be08904 (HEAD -> master) HEAD@{2}: commit (initial): first commit

3)分支(branch)

在版本控制过程中,同时推进多个任务,为每个任务,我们就可以创建每个任务的单独分支。使用分支意味着程序员可以把自己的工作从开发主线上分离开来,开发自己分支的时候,不会影响主线分支的运行。对于初学者而言,分支可以简单理解为副本。

git基本使用_第15张图片

使用分枝的好处

  • 同时并行推进多个功能开发,提高开发效率。
  • 各个分支在开发过程中,如果某一个分支开发失败,不会对其他分支有任何影响。失败的分支删除重新开始即可。

常用命令:

$ git branch -h
usage: git branch [] [-r | -a] [--merged] [--no-merged]
   or: git branch [] [-f] [--recurse-submodules]  []
   or: git branch [] [-l] [...]
   or: git branch [] [-r] (-d | -D) ...
   or: git branch [] (-m | -M) [] 
   or: git branch [] (-c | -C) [] 
   or: git branch [] [-r | -a] [--points-at]
   or: git branch [] [-r | -a] [--format]

Generic options
    -v, --verbose         show hash and subject, give twice for upstream branch
    -q, --quiet           suppress informational messages
    -t, --track[=(direct|inherit)]
                          set branch tracking configuration
    -u, --set-upstream-to 
                          change the upstream info
    --unset-upstream      unset the upstream info
    --color[=]      use colored output
    -r, --remotes         act on remote-tracking branches
    --contains    print only branches that contain the commit
    --no-contains 
                          print only branches that don't contain the commit
    --abbrev[=]        use  digits to display object names

Specific git-branch actions:
    -a, --all             list both remote-tracking and local branches
    -d, --delete          delete fully merged branch
    -D                    delete branch (even if not merged)
    -m, --move            move/rename a branch and its reflog
    -M                    move/rename a branch, even if target exists
    -c, --copy            copy a branch and its reflog
    -C                    copy a branch, even if target exists
    -l, --list            list branch names
    --show-current        show current branch name
    --create-reflog       create the branch's reflog
    --edit-description    edit the description for the branch
    -f, --force           force creation, move/rename, deletion
    --merged      print only branches that are merged
    --no-merged   print only branches that are not merged
    --column[=