Posts Git基本使用方法(一):本地单分支篇
Post
Cancel

Git基本使用方法(一):本地单分支篇

本文环境: WSL: Ubuntu-18.04, git version 2.17.1

一、 前言

当你的项目需要有多个版本同时存在、特别是需要维护的代码分散在不止一台计算机上的时候, git一类的版本控制工具就变得必要了

本文侧重快速上手git的入门内容

二、 起步: 创建本地仓库

你可以选择新建空仓库

  • 命令中没有仓库名称时, 在当前文件夹新建仓库
  • 使用仓库名称时, 新建一个同名文件夹作为仓库
1
git init [仓库名称]

也可以从已有仓库开始

  • 没有指定本地目录时, 在当前文件夹下新建与仓库同名的文件夹作为仓库
  • 仓库地址可以是本地, 也可以是网络路径 (经常使用git clone [网络地址]来下载代码)
1
git clone [仓库地址] [本地目录]

git如何识别当前文件夹是否为仓库? 在创建仓库的时候, git就在其目录中新建了一个名为.git的隐藏文件夹, 有关信息就保存在那里, 如果删除.git文件夹, git就不在将其识别为仓库

三、 基础知识: 工作模式

在学习更多命令之前, 看一下git的工作模式

工作模式

我们先忽略本地版本库和远程仓库的操作, 将注意力集中在右半部分, 我们注意到:

  • 通过add和commit实现从工作区提交代码到仓库, 通过checkout从仓库中取回代码
  • 在开发过程中直接操作的是工作区(workspace), 想要提交到仓库就必须经过暂存区(stage)

四、 基础命令

4.1 查看当前状态(status)

在commit之前查看当前状态是个好习惯, 能有效避免我们提交一些不希望被提交的东西

通过这个命令, 我们可以观察到工作区/暂存区/仓库之间的差异, 预测未来的操作造成的影响

1
git status

典型的status输出

上图是一个典型的status输出: 除branch信息外, 其余分为三段

  • Changes to be committed: 没有被提交的更改——这里指已经加入暂存区但没有提交(commit)到仓库的文件
  • Changes not staged for commit: 没有加入暂存区的更改——这里指在工作区已经保存的更改, 但没有加入(add)到暂存区
  • Untracked files: 未追踪的文件——指从来没有加入暂存区、或加入到.gitignore中的文件

逻辑十分明确:

  • Changes to be committed: 暂存区和仓库比对区别
  • Changes not staged for commit: 工作区和暂存区比对区别
  • Untracked files: 工作区被git忽略的文件

这样我们就知道我们的操作会造成怎样的影响

4.2 添加(add)、提交(commit)

用于从工作区向暂存区提交更改, 基础用法非常简单:

1
2
git add [路径] 
git commit (-m '提交附带的评论')

看一个例子:

现在我们有一个仓库, 我对其四个文件(在工作区)做了修改, 然后查看status:

1
git status

status

可以看到四个文件均处于Changes not staged for commit的状态, 即未向暂存区提交

现在我们添加READMEgif_maker.py到暂存区

1
2
git add README.md
git add gif_maker.py

可以看到被添加的文件转为Changes to be committed

add

这时我们试着commit一次

1
git commit

comment

可以看到弹出文本编辑框, 根据提示可以知道, 你需要对这次commit做出评论comment,这就像Github在提交的时候也需要做出评论

写好保存退出后就看到commit成功了

success

再查看一下status:

status

可以看到, 原来的Changes to be committed已经被提交, 其余的内容不变

如果使用-m做出评论, 则不会弹出文本编辑界面

至此, 我们完成了一次对仓库的修改

另外两个选项:

1
2
git commit -a 
git commit -amend
  • -a自动把已追踪但没有添加到暂存区的文件添加到暂存区并提交
  • -amend使用一次新的commit,替代上一次提交, 如果代码没有任何新变化,则用来改写上一次commit的提交信息

4.3 移除(rm)、移动(mv)

这里的rmmv指的是git rmgit mv

这两个命令和系统命令rm/mv的区别和联系在于

  • 都会删除或移动工作区的文件
  • git rm/git mv除了对工作区进行操作外, 也对暂存区进行操作

这意味着:

  • 使用rm删除文件后不能直接commit, 因为暂存区仍存在这个文件
  • 使用git rm删除文件后可以commit, 因为暂存区的文件也被删除、和仓库产生了差异

补充一点: 如果不小心使用rm删除工作区文件, 之后还可以使用git rm对暂存区内的文件进行删除

对于git mv, 其实质上就是进行了以下操作:

1
2
3
mv file_old file_new
git rm file_old
git add file_new

无论是git mv还是git rm, 都对暂存区进行了对应的操作, 所以作用后可以直接commit

4.4 checkout(恢复文件部分)

git checkout有两部分功能: 切换分支和恢复文件, 有关分支的内容放在下一篇讲, 这篇只说恢复文件的部分

回看一下上文的工作模式示意图, checkout是从本地仓库指向(取文件到)工作区的过程, 其实并不准确, checkout也可以从暂存区取回文件

当我们想取消在工作区的修改, 恢复到上一次提交的状态时, 仓库和暂存区就发挥了备份职能——从中恢复文件

从当前仓库中取文件使用方法:

1
git checkout HEAD [文件名]

从暂存区中取文件使用方法(两个短横是为了避免与切换分支的命令混淆):

1
git checkout -- [文件名]

如果对分支此有疑问不妨先跳过, 下一篇文章对分支会有详细的说明

我们同样看一个例子:

当我们执行完git rm命令后, 一个文件被从工作区和暂存区删除了,

deleted

现在我们想找回这个文件, 因为暂存区的文件也被删除了, 所以我们从当前仓库中取,

1
git checkout HEAD gif_maker.py

查看当前状态

当前状态

可以看出来, 从Changes to be committeddeleted消失了, 这说明此文件已经在暂存区和工作区同时恢复了

同样, 当暂存区中的文件幸存时(比如使用rm而不是git rm), 我们可以直接使用暂存区的备份, 这时只需要使用

1
git checkout -- [文件名]

就可以完美地恢复了

4.5 重置/回退(reset)

这是我们回退版本常用的方法, 常用的形式如下

1
git reset [程度选项] [commit(版本)] [回退文件]
  • 程度选项有--soft, --mixed--hard三种
  • 版本可以用HEAD来表示:
    • HEAD表示当前版本
    • HEAD^表示上一个版本
    • HEAD^^表示上上一个版本
    • HEAD~1表示上一个版本
    • HEAD~2表示上上一个版本
    • 以此类推
  • 另外版本可以用一定的哈希码表示, 使用git log查看日志可以看到commit

commit hash

  • 回退文件选项不指明, 则全部文件回退
  • 版本不指明, 则为当前版本(HEAD)
  • 程度选项不指明, 则为--mixed选项

下面介绍三种不同程度, 从softmixed再到hard, 程度由浅到深

这里引用git官网的图就可以很好地说明问题了

在下图的情况下, 当前的工作区、暂存区、仓库都是v3版本, 我们看一下三种模式回退的不同之处:

soft

mixed

hard

一目了然的区别! 这里需要尤其注意的是: hard模式虽然看起来只是把修改递进到了工作区, 其实是危险的选项, 在不确定稳健的情况下尽量不要使用

4.6 比较差异(diff)

正如其名, diff用来比较各种差异

  • git diff (路径)可以比较工作区和暂存区的差异
  • git diff --stat (路径)查看简单的统计结果
  • git diff --cached (路径)git diff --staged (路径)可以比较暂存区和仓库的区别
  • git diff HEAD (路径)可以查看自上次提交以来工作树(包括仓库、暂存区和工作区)的更改
  • git diff [版本1] [版本2] (路径)可以比较两个版本的差异
  • git diff [分支1] [分支2] (路径)可以比较两个分支的差异
This post is licensed under CC BY 4.0 by the author.

使用Python发送带有附件的邮件

Git基本使用方法(二):本地多分支篇