Git 最基本的命令

Saturday, Jul 4, 2020 | 10 | Saturday, Jul 4, 2020

@

针对 Git 最基本的命令的详细说明 ⑅︎◡̈︎*

 
——> 全文约 4800 字 <——
 
 
绝对是全网最通俗最详细的学习教程!一片空白的我都能学会你还在等什么!
↓    ↓    ↓    ↓    ↓    ↓    ↓    ↓
 
  • 写在最前:

    若想直接了解关于 Git 在私有仓库和公共仓库中的使用命令,请 点击这里 直达结论。

Git 最基本的命令

之前的文章中我对 Git 中最基础的几类命令有过形象地解释,这里再 po 一次:

我在本地电脑的 A文件夹 下修改某文件中的一行代码,这个修改信息就被 git 自动发现了,它把这个信息记在自己的小本子上,我们可以把每次 被修改过的A文件夹整体 看作是一个新的犯人,使用 git add 把这个犯人放到缓存区里暂时拘留,再通过 git commit 把这些文件放到本地的仓库正式坐牢,而仓库里储存了每个犯人的犯罪信息(我自定义的信息),通过 push 可以把仓库里的犯人同步到远程仓库,这时候远程仓库和本地仓库的信息就一样了。

-------------------------------------------------------------------------

Git 中最基础的命令就是 cloneremotepull/fetchaddcommitpush ,一句话概括各个命令的作用:

-------------------------------------------------------------------------

对于一个项目而言,如何在本地电脑上从无到有,如何和远程仓库建立连接,提交自己的成功,有如下七步流程:

在本地目录中建立 Git 仓库 → 编辑本地目录的内容 → 将本地修改或新增内容加入到本地缓存区本地缓存区内容添加进本地仓库在本地仓库关联远程仓库本地仓库推送到远程仓库从远程仓库下拉更新其他人更改的内容到本地仓库

接下来我们针对每一步进行详细的介绍,Git 中最基础的命令如何在过程中使用。

获取 Git 仓库

通常来说,我们有两种获取 Git 项目仓库的方式:

  1. 从其它服务器 git clone 一个已存在的 Git 仓库;
  2. 将尚未进行版本控制的本地目录转换为 Git 仓库。

这两种方式都会在你的本地电脑上得到一个就绪的 Git 仓库。

-----------------------------------------------------
  • 克隆( git clone )远程仓库

如果你想获得一份已经存在了的 Git 仓库的拷贝,比如说,你想为某个开源项目贡献自己的一份力,这时就要用到 git clone 命令。Git 克隆的是该 Git 仓库服务器上的几乎所有数据,当你执行 git clone 命令的时候,默认配置下远程 Git 仓库中的每一个文件的每一个版本都将被拉取下来(这也就意味着,如果你的服务器的磁盘坏掉了,你通常可以使用任何一个克隆下来的用户端来重建服务器上的仓库)。

克隆仓库的命令是 git clone <url> 。 比如,要克隆我的某个仓库,可以复制该仓库的地址,并使用下面的命令:

$ git clone https://github.com/CaymanHK/repository_name.git # .git 其实要不要加上都行

这会在终端运行的 当前目录下 创建一个名为 repository_name 的目录,并在这个目录下初始化一个 .git 文件夹, 从远程仓库拉取下所有数据放入 .git 文件夹,然后从中读取最新版本的文件的拷贝。 如果你进入到这个新建的 repository_name 文件夹,你会发现所有的项目文件已经在里面了。

如果你不想要本地仓库的名字叫做 repository_name ,你希望叫做 cayman_edit ,命令如下:

$ git clone https://github.com/CaymanHK/repository_name.git cayman_edit # 通过额外的参数指定本地仓库名字

-------------------------------------------------------------------------

Git 支持多种数据传输协议,上面的叙述使用的是 https:// 协议,不过你也可以使用 git:// 协议或者使用 SSH 传输协议,比如 user@server:path/to/repo.git ,以后将会对这三种协议进行详细的叙述。

-----------------------------------------------------
  • 在现有本地目录中初始化( git init )本地仓库

如果你有一个尚未进行版本控制的项目目录,想要用 Git 来管理或者控制,那么首先需要进入该项目目录中:

$ cd /Users/user/cayman_project # 进入现有的本地目录

通过以下命令在 /Users/user/cayman_project 目录中初始化一个本地仓库:

$ git init

该命令将创建一个名为 .git 的子目录,这个子目录含有你初始化的 Git 仓库中所有的必须文件,这些文件是 Git 仓库的骨干。 但是在这个时候,我们仅仅是做了一个初始化的操作,你的项目里的文件还没有被跟踪(关于跟踪一项,之后会专门写文章介绍),接下来就是追踪项目文件,或者说将本地修改或新增内容加入到本地缓存区( git add

git add

git add 命令的作用是将我们需要提交的代码从本地的工作区添加到缓存区,具体命令如下:

# 1. add 新添加和修改的文件到缓存区,但是不包括删除的文件
$ git add . # . 表示当前目录

# 2. add 修改和删除的文件到缓存区,但是不包括新添加的文件
$ git add -u # u 指的是 update ,对已有记录(已跟踪的文件)进行更新
$ git add --update # 和 -u 相同作用

# 3. add 所有的变动到缓存区
$ git add -A # A 就是 all 的意思
$ git add --all # 和 -A 相同作用

git add 通过 git add <files/directories> 命令进行文件追踪,如果参数是目录的路径,该命令将递归地跟踪该目录下的所有文件,所以我们也可以对单个文件进行跟踪,但是很明显一般情况使用不到。

接下来就是将本地缓存区内容添加进本地仓库

git commit

git commit 主要是将暂存区里的改动给提交到本地的版本库。每次使用 git commit 命令我们都会在本地版本库生成一个 40 位的哈希值,这个哈希值也叫 commit-id ,commit-id 在版本回退的时候非常有用,它相当于一个快照,可以在未来的任何时候通过与 git reset 的组合命令回退到指定版本。

关于 git commit 具体用法如下:

  • 将缓存区的文件提交到本地仓库
$ git commit -m "提交信息记录" # 提交信息会显示在远程仓库上

  • ⚠️ 不建议的用法 ⚠️
$ git commit -a -m “提交信息记录”
$ git commit –am “提交信息记录” # 两者效果相同

-a 参数可以将所有已跟踪文件中的执行修改或删除操作的文件(不包括新添加的文件)都提交到本地仓库,即使它们没有经过 git add 添加到暂存区,该用法相当于先执行 git add -u 再执行 git commit -m "提交信息记录" ,不建议这么使用。

  • 提交内容和信息的修改
$ git commit --amend

在终端的当前工作目录下输入以上命令会进入文本编辑界面,在该界面可以进行文件的追加提交或者提交信息的修改(毕竟手残党经常会手抖打出一些奇奇怪怪的信息是吧),通过该命令可以在不增加一个新的 commit-id 的情况下将新修改的代码或者提交信息追加到前一次的 commit-id 中。

  • 查看帮助
$ git commit --help

ps. 日常开发并不需要了解 git commit --help 中的内容。

commit 完后就是在本地仓库关联远程仓库

git remote

到目前为止我们的本地仓库已经建立完成,并且仓库中的内容准备好上传,但是在上传前还有最后一个问题:我们要把东西推送到哪里?

在第一次推送本地仓库前,我们得在当前的工作目录下设置远程仓库的地址,命令如下:

git remote add <shortname> <url>

$ git remote add origin https://github.com/CaymanHK/China.git # .git 加不加都行

$ git remote add cn https://github.com/CaymanHK/China.git # .git 加不加都行

以上两行唯一的区别就是 <shortname> ,其中 cn 是后面整个 URL 的自定义简称,但是一般 Git 默认使用 origin ,因为 origin 这个名字一看就知道是远程仓库。

关于 url 中的协议,这里使用的是 https:// 协议,你也可以使用 git:// 协议或者使用 SSH 传输协议,上文对此有进行过阐述。

我们可以查看关联的远程仓库的相关信息:

$ git remote # 查看关联的远程仓库的名称

$ git remote -v # 查看关联的远程仓库的详细信息

如果要修改远程仓库的地址,有如下两种方法:

  1. 先删除再添加:
$ git remote remove <shortname> # 通过 git remote 查看远程仓库名称 ( shortname )
$ git remote add origin <url>
  1. 直接修改:
$ git remote set-url origin <new_url>

关联完远程仓库后,就是将本地版本库的分支推送到远程服务器上对应的分支

git push

git push 的命令格式是:

git push <远程主机名> <本地分支名>:<远程分支名>

这里的 <远程主机名> 指的就是上一节所说的 <shortname> ,直观解释就是把本地仓库的某分支推送到远程仓库的某分支,一般而言我们把本地仓库和远程仓库分支都设为同名 master ,因此命令如下:

  • 第一次推送分支

由于远程库是空的,我们第一次推送 master 分支时,加上 -u 参数,Git 不但会把本地仓库的 master 分支内容推送的远程仓库的 master 分支,还会把本地的 master 分支和远程的 master 分支关联起来,在以后的推送或者拉取时就可以简化命令。

$ git push -u origin master

  • 平常使用的命令:

如果远程分支被省略,则表示将本地分支推送到与之存在追踪关系的远程分支:

$ git push origin master

  • 更简化的命令:

如果当前分支与远程分支之间存在追踪关系,则本地分支和远程分支都可以省略:

$ git push origin # 将本地当前分支推送到origin主机的对应分支

如果当前分支只有一个远程的追踪分支,那么主机名都可以省略:

$ git push

  • ⚠️ 非常危险的用法,慎用 ⚠️
$ git push --force
$ git push -f
$ git push --force origin
$ git push origin master --force
$ git push origin master -f
$ git push -f origin master

这几种用法效果一样,当然我不是在告诉你这样用有多好,网上输入该代码随便一查都是警告和惨案…据说美国2018年有程序员因为用了这个命令发生了枪击案…

如果远程仓库的版本比本地版本更新,推送时 Git 会报错,要求先在本地做 git pull 合并差异,然后再推送到远程主机,这是正常合理的代码提交流程。在这时候使用 --force 会将本地分支的提交强制覆盖远端推送分支的提交。也就是说,如果其他人在相同的分支推送了新的提交,你的这一举动将删除他的提交内容。

因此应避免在公有的远程仓库使用这样的命令,当然对于个人私有的仓库就无所谓了。

针对这个用法,今天我发现本地某仓库的 .git 文件太大了,因此删除了该文件,并重新生成该文件,这意味着本地仓库的所有提交记录都被删除了,同时我在本地进行了不少的代码改动,因此使用 push origin master -f 强制推送到 GitHub 的远程仓库的时候发现,远程仓库的提交记录已被清空,原本几十个 commit 信息现在只剩下一个。

‍ ‍

当他人对远程仓库的代码进行了更新之后,我们就需要从远程仓库下拉更新其他人更改的内容到本地仓库,拉取远程仓库的代码方式有两种:

git fetch

在作用上 git fetchgit pull 的功能是大致相同的,都是起到了更新代码的作用,区别如下:

  • git fetch 是将远程仓库的最新内容拉到本地并记录在 .git/FETCH_HEAD 中,用户在检查了以后自行决定是否合并到本地分支中。

  • git pull 基于本地的 FETCH_HEAD 记录,比对本地的 FETCH_HEAD 与远程仓库的版本号,然后 git fetch 获得当前的远程分支的后续版本的数据,然后利用 git merge 将其与本地的分支合并,可以认为是 git pullgit fetchgit merge 两个步骤的合并。

我们可以借助下图来加深理解这两者的区别:

image-20200706232000986

git fetchgit pull 类似,这里不再赘述,仅作简单的解释,其命令格式如下(这时候 <远程分支名> 在前面):

git fetch <远程主机名> <远程分支名>:<本地分支名>

对于只有一个远程仓库甚至远程仓库只有一个 master 远程分支的而言,我们可以使用如下命令:

$ git fetch origin master # 将 master 分支下载到本地仓库当前分支

# 甚至可以更简化
$ git fetch

在比较本地仓库的 master 分支和远程仓库的 master 分支时,有如下两种命令:

  • 直接对比合并
$ git fetch origin master # 将远程仓库的 master 分支下载到本地当前 branch 中
# $ git log -p FETCH_HEAD # 查看从远程仓库取回的更新信息(可以不查看)
$ git log -p master ..origin/master # 比较本地的 master 分支和 origin/master 分支的差别(关于 .. 的作用我也不清楚)
$ git merge origin/master # 进行合并

  • 本地创建暂时的分支 temp
$ git fetch origin master:temp # 在本地仓库新建一个 temp 分支,并将远程 origin 仓库的 master 分支代码下载到本地 temp 分支
# git diff <local branch> <remote>/<remote branch>
$ git diff temp # 比较本地仓库代码与远程仓库代码的区别
$ git merge temp # 将 temp 分支合并到本地 master 分支
$ git branch -d temp # 如果不想保留 temp 分支,可以将其删除

git pull

实际的 git pull 过程可以理解为:

$ git fetch origin master # 将远端的 master 分支拉取最新内容
$ git merge FETCH_HEAD # 将拉取的最新内容与当前分支合并

git pull 也和 git push 类似,格式如下:

git pull <远程主机名> <远程分支名>:<本地分支名>

git pull 合并后可能会出现冲突,需要手动解决冲突,错误提示如下:

# 更新的代码与本地的修改代码有冲突,先提交你的改变或者先将本地修改暂存起来
error: Your local changes to the following files would be overwritten by merge:
Please commit your changes or stash them before you merge.

关于如何解决冲突,将会在以后的文章中进行详细的介绍。

git pull 更新代码的话比较简单粗暴,但是根据 commit-id 来看,它们的实现原理并不相同。在实际使用中,git fetch 更安全一些,因为在 git merge 之前,我们可以查看代码的更新情况,再决定是否进行合并。

总结

前面碎碎念把每一类基本命令都详细地介绍了一番,现在用最简单的话总结一下:

  • 自用的私有仓库
$ cd /Users/user/cayman_project # 进入现有的本地目录
$ git init # 第一次使用要初始化一个本地仓库
$ git remote add origin https://github.com/CaymanHK/China.git # 第一次使用要关联远程仓库地址
$ git add -A # 把所有变化加入缓存区
$ git commit -m "自定义提示信息" # 提交到本地仓库
$ git push origin master # 推送到远程仓库 origin 的 master 分支
  • 公有仓库
$ cd /Users/user/cayman_project # 进入现有的本地目录
$ git clone https://github.com/CaymanHK/repository_name.git # 第一次使用要把远程仓库的内容克隆到本地

# 上传
$ git add -A # 把所有变化加入缓存区
$ git commit -m "自定义提示信息" # 提交到本地仓库
$ git push origin master # 推送到远程仓库 origin 的 master 分支

#下拉
$ git fetch orgin master # 将远程仓库的 master 分支下载到本地当前 branch 中
$ git merge origin/master # 进行合并

本文结束。

© 2020 - 2026 Kays Blog ⑅︎◡̈︎*

🌱 Powered by Hugo with theme Dream.

憨批の自我介绍
🍺 Kayman' Blog 🏎️

这个博客用来记录一些生活&学习上的事情 ⑅︎◡̈︎*

一名憨憨CRUD专家,现就职于Shopee ,数据鸡架的 Flink 方向

业余时间只剩下 羽毛球🏸️|篮球🏀|德州♠️|打游戏🎮|肥宅🥤 了……

-- 2022 年 02 月 08 日更新 --

一名憨憨CRUD专家,现即将从就读于 🏫 北大青鸟毕业

业余时间会做开源和一些别的项目啥也不会做

目前准备去1075了,顺便捣鼓些Geek Proj,养老的同时培养点兴趣驱使方向。


在北大最好的朋友是 江栽花 ,我们一个负责吹牛皮一个负责去 GayHub 偷别人的优秀代码,完成过很多烂番茄项目,搞过一段时间的磕盐。

尽管也没人认识我们,但是还是客套地说一下

-- 2021 年 06 月 18 日更新 --
技术栈 & Project

主要的技术栈是:

  • 目前工作的方向是 Flink ˙Ꙫ˙

  • Java ˙Ꙫ˙

  • Python ˙Ꙫ˙

  • SQL ˙Ꙫ˙

  • 一点点的 html + css + js 🤏

  • 一点点的 shell 🤏


做过啥:

(其实啥也没做过 ⑅︎◡̈︎*)

友链 :💬 I will put some of my friends' and technical Dalaos' blogs HERE so as to encourage myself (umm though it may not work hahah~) 📣 😤
⑅︎◡̈︎*

My BEST FRIEND in PKU, so l list her at the first row.

I modify my front-end framework from him. List him here so as to thx him~
加载每日一言中...