头图

你的文件需要 git,常用命令

LhkATi-veNBCB

上一节主要介绍了

  1. git 是什么?
  2. git 能做什么?
  3. github 是什么?如何注册与简单使用
  4. git 的配置文件
  5. git 单用户与多用户的配置
  6. github page 的简单使用

好了,工具是有了,那么我们就要了解如何使用它来提高我们的效率,甚至解决工作中较常出现的问题。

但凡是个程序员,必须要学会 git 的基本操作,无论是学生时代,还是工作职场,多多少少会点 git 的命令。

嗯,鄙人也是从学生时代正在慢慢跨越到工作中,从以前简单的git pushgit pull扩展更多其他常用的命令,以免我们在工作上遇到问题不知所措,甚至出现抓狂烦恼的一幕。

不过,我极力推荐一个在线交互式 git 命令学习的网站:https://learngitbranching.js.org/

好了,多余的话也不再多说了,都在酒里...

CetDM7-D2QD7S

创建仓库

假如,我们现在想要有一个这样的需求:本地的项目代码想上传到的远程仓库,该如何做?

我们思考一下,本地仓库该如何和远程仓库关联呢?嗯,这是个问题呀

我做了一个这样的实验,我在桌面上创建了一个文件夹:git-test

文件夹中存放了一个名为 README.md 的文件,然后终端输入一个git init的命令,这时候我们cd.git目录找到 config 文件

[core]
    repositoryformatversion = 0
    filemode = true
    bare = false
    logallrefupdates = true
    ignorecase = true
    precomposeunicode = true
[user]
    email = xxx@gmail.com
    name = Dreamcats

好,我们接下来去 github 上创建一个仓库,如图:

ZngY1Y-j4zQk2

关于如何创建仓库,这里暂时就不说了咩

从图中可以看到

  1. 远程仓库名为:ss-test
  2. 如果是新项目,图中很明显教我们如何做
echo "# ss-test" >> README.md # 给README.md文件写入# ss-test
git init # git init 初始化命令,你就理解为生成一堆为仓库服务的git信息
git add README.md # 这里在本地仓库修改的文件提交到本地暂存区
git commit -m "first commit" # 给本次所提交的文件,给个注释,理解为版本注释
git branch -M main # branch意为分支,git仓库的新功能,分支功能,为了协同,也为了不同版本
git remote add origin git@github.com:DreamCats/ss-test.git # 本地仓库关联到远程仓库的桥梁
git push -u origin main # 直接打通桥梁,开始上传
  1. 如果是已有 git init 的项目,图中也告诉你如何操作
git remote add origin git@github.com:DreamCats/ss-test.git # 必须有的,和远程仓库关联
git branch -M main # 仓库必须有个分支,当然你可以选择master分支
git push -u origin main # 推送操作

我呢,首先在终端输入git remote add origin git@github.com:DreamCats/ss-test.git

这个时候 config 文件出现了变化,我们瞧一瞧:

[core]
    repositoryformatversion = 0
    filemode = true
    bare = false
    logallrefupdates = true
    ignorecase = true
[user]
    email = xxx@gmail.com
    name = Dreamcats

[remote "origin"]
    url = git@github.com:DreamCats/ss-test.git
    fetch = +refs/heads/*:refs/remotes/origin/*

多了 remote origin,意味着和远程仓库关联,但是我们少了一个重要的环节,你虽然和远程仓库搭建了桥梁,但是仓库是有个分支的概念,恰好我们少了一个环节,如果这个时候,你执行了

git add README.md
git commit -m ":tada: create init push"

终端告诉你:

fatal: 当前分支 master 没有对应的上游分支。
为推送当前分支并建立与远程上游的跟踪,使用

    git push --set-upstream origin master

也就是说,你本地仓库的分支是 master,而远程仓库假如有很多分支,它不知道你要将本地分支上传到远程仓库中的哪个分支,因此你还需要绑定一个分支

git push --set-upstream origin master

结果显而易见:

↳ git push --set-upstream origin master                   128 ↵  00:12:21 
枚举对象中: 3, 完成.
对象计数中: 100% (3/3), 完成.
写入对象中: 100% (3/3), 226 字节 | 226.00 KiB/s, 完成.
总共 3(差异 0),复用 0(差异 0),包复用 0
To github.com:DreamCats/ss-test.git
 * [new branch]      master -> master
分支 'master' 设置为跟踪来自 'origin' 的远程分支 'master'。

3HVwkD-DqIrpb

如图所示,我们能看到 README 文件的信息,也能看到修改文件的注释,如果再仔细一点,也能看到版本号,分支等信息。

这个时候,我们再回头看看本地仓库中.git的 config 文件:

[core]
    repositoryformatversion = 0
    filemode = true
    bare = false
    logallrefupdates = true
    ignorecase = true
[user]
    email = xxx@gmail.com
    name = Dreamcats

[remote "origin"]
    url = git@github.com:DreamCats/ss-test.git
    fetch = +refs/heads/*:refs/remotes/origin/*
[branch "master"]
    remote = origin
    merge = refs/heads/master

出现了分支参数,意味着,我们和远程仓库关联需要这么几个参数:user、remote、branch

当然,很多信息都在.git文件夹中,有兴趣的童鞋,可以详细研究一波,多说一句:学技术,得钻研才行...

.
├── COMMIT_EDITMSG # 嘿嘿,commit注释写错了,这里可以重新修改撒
├── HEAD
├── config # 本地仓库和远程仓库关联的入口信息
├── index
├── logs # 这个很重要,可以看到版本号和远程仓库版本号
│   ├── HEAD
│   └── refs
│       ├── heads
│       │   └── master
│       └── remotes
│           └── origin
│               └── master
└── refs # 这里详细记录你的本地仓库和远程仓库的信息
    ├── heads
    │   └── master
    ├── remotes
    │   └── origin
    │       └── master
    └── tags

18 directories, 27 files

从上面你可以熟悉几个以下命令:

  1. git init
  2. git remote add origin xxx.git
  3. git add
  4. git commit -m
  5. git push --set-upstream origin xxx

上传已有仓库(分支)

假如,我们现在有这么个需求,远程仓库已经有了项目,我们本地仓库想关联远程仓库,但是其他分支,比如 feat_test,那么该如何做

两种情况:

  1. 没有关联远程仓库,想关联远程仓库,并上传新的分支上,该如何做?

第一步该做什么?那肯定是初始化

git init

远程仓库肯定有 master 了,一般情况下,本地仓库不要默认 master,要创建一个新的分支,比如 feat_test

git checkout -b feat_test

or

# 新建项目,可直接-m
git branch -m feat_test
# 输入过后,自动切换feat_test分支

接着,关联远程仓库了撒,

git remote add origin git@github.com:DreamCats/ss-test.git

目前,本地仓库分支 feat_test,自然远程仓库没有,所以必须执行下面这句话

# 注意
git add README.md
git commit -m ":tada: create init push"
git push --set-upstream origin feat_test

看结果

↳ git push --set-upstream origin feat_test                      00:44:50 
枚举对象中: 3, 完成.
对象计数中: 100% (3/3), 完成.
写入对象中: 100% (3/3), 225 字节 | 225.00 KiB/s, 完成.
总共 3(差异 0),复用 0(差异 0),包复用 0
remote:
remote: Create a pull request for 'feat_test' on GitHub by visiting:
remote:      https://github.com/DreamCats/ss-test/pull/new/feat_test
remote:
To github.com:DreamCats/ss-test.git
 * [new branch]      feat_test -> feat_test
分支 'feat_test' 设置为跟踪来自 'origin' 的远程分支 'feat_test'。

nPFeIq-9MzUnt

V2VVbk-OXXisP

  1. 你在已有的远程仓库并关联了分支,该如何做?

比如,你从 master 拉取了项目,目前本地仓库的分支是 master,或者是其他分支,那么接下来我们该如何做

很简单,直接创建新分支

git checkout -b feat_test2

此时,我修改了 README.md 文件,将test1修改为test2

git add README.md
git commit -m ":tada: create init push"
git push --set-upstream origin feat_test2

看结果:

↳ git push --set-upstream origin feat_test2               128 ↵  00:55:41 

枚举对象中: 5, 完成.
对象计数中: 100% (5/5), 完成.
写入对象中: 100% (3/3), 254 字节 | 254.00 KiB/s, 完成.
总共 3(差异 0),复用 0(差异 0),包复用 0
remote:
remote: Create a pull request for 'feat_test2' on GitHub by visiting:
remote:      https://github.com/DreamCats/ss-test/pull/new/feat_test2
remote:
To github.com:DreamCats/ss-test.git
 * [new branch]      feat_test2 -> feat_test2
分支 'feat_test2' 设置为跟踪来自 'origin' 的远程分支 'feat_test2'。

paj505-foXcM7

从以上你可以了解的命令:

  1. git checkount -b xxx
  2. git branch -m xxx
  3. git branch -a (查看远程所有分支)

我稍微补充一些,如何拉取远程分支

拉取远程分支

  1. 当然你可以拉取 master 玩一玩
git clone git@github.com:DreamCats/ss-test.git
git checkout feat_test

结果:

↳ git checkout feat_test                                        01:03:45 
分支 'feat_test' 设置为跟踪来自 'origin' 的远程分支 'feat_test'。
切换到一个新分支 'feat_test'
↳ cat README.md                                                 01:04:01 
test1

当然,你也可以继续切换其他分支

git checkout feat_test2

结果

git checkout feat_test2                                       01:04:12 
分支 'feat_test2' 设置为跟踪来自 'origin' 的远程分支 'feat_test2'。
切换到一个新分支 'feat_test2'
cat README.md

test2
  1. 直接拉取远程分支

    1. 创建文件夹:xxx
    2. 进入 xxx 文件下,终端输入git init
    3. 接着,建立远程仓库连接:git remote add origin git@xxxx.git
    4. 拉取远程分支到本地:git fetch origin xxx(远程分支)
    5. 拉取远程文件到本地:git pull origin xxx(远程分支)
    6. 结束

合并

  1. 合并 master

假如,你现在处于 feat_test2 分支上,你现在开发完成了, 想要合并到 master 上,该如何操作?

首先,我们需要切换到 master 分支,毕竟merge xxx的意思是将 xxx 合并到你现在所在的分支上,废话不多说

git checkout master
git merge feat_test2 --allow-unrelated-histories

注意:合并分支,可能会出现:fatal: refusing to merge unrelated histories,所以,在命令后面加个--allow-unrelated-histories

  1. 合并其他分支
git checkout feat_test
git merge feat_test2 --allow-unrelated-histories

注意:如果git checkout feat_test出现问题,请拉取远程分支到本地仓库,git fetch origin feat_test

  1. master 合并覆盖分支(冲突),如何解决

那就慢慢解决呗,解决冲突再上传即可

注意:一般公司不会让你随便 merge request...

小插曲:git rebase 和 git merge 的区别

从以上你可以学到的命令:

  1. git checkout xxx
  2. git merge xxx --allow-unrelated-histories

删除分支

我们知道仓库有本地和远程,那么在咱们删除分支,不仅要删本地,还要删远程,如何操作?

git branch -d feat_test # 本地
git push origin -d feat_test # 远程

olfSIy-LOq3ZT

从图上看,远程 feat_test 被删除了

从以上可以学到的命令:

  1. git branch -d xxx
  2. git push origin -d xxx

好了,创建,合并,删除,都讲完了, 是不是轮到版本了?

文件回退

我敢保证,你真的遇到想让某个文件恢复当一个版本,或者上上个版本,或者上上上上个版本... 我在套娃?好像也不是

我做个实验,我现在在工程目录下创建一个 Hello.txt 文件,打算在这个文件中,做各种荒唐之事...

↳ tree .                                                  127 ↵  16:20:09 
.
├── hello.txt
└── README.md

0 directories, 2 files

hello 文件的内容

hello

我现在试一试git checkout Hello.txt

出现了一个小小的错误

error: pathspec 'hello.txt' did not match any file(s) known to git

从而能看出来,不让我们撤销新增的文件撒,checkout 撤销的是修改的文件,要不然我们玩一下,我快速的提交一波哈,不慌,我发现,文章好长...

你们看完真心不易,下次录个视频也挺不错的...

git add hello.txt
git commit -m ":sparkles: hello.txt"
git push origin master

我继续在hello.txt文件下添加一行world,然后咱们使用git checkout hello.txt

↳ git checkout hello.txt                                        16:34:28 
Updated 1 path from the index

PKDbe4-1E1Ubi

注意,这哥们可不能文件回退某个版本

再注意,如果你提交了 add,亦或者 commit 了,那么 checkout 没啥子效果,不信你试试,反正我试过了...嘻嘻嘻

从以上你可以学到的命令:

  1. git checkout xxx(某个文件,撤销修改)
  2. git checkout . (撤销所有修改的文件)

但是如果真的 add 了,或者 commit,想回退,咋整?

回退版本

  1. 修改,无 add,无 commit
git checkout xxx # 回到开始无修改的仓库
  1. 修改,有 add,无 commit
git restore --staged <file>... # 同上
or
git reset <file>... # 同上
  1. 修改,有 add,有 commit
git reset HEAD^ # 同上,但是,默认的方式--mixed,已修改的代码不会被丢弃,可以继续配合 checkout, 如果一步操作,更换参数--hard

注意:说明几个参数

  • HEAD^的意思是上一个版本,也可以写成 HEAD^1,如果你进行了 2 次 commit,也可以写成 HEAD^2
  • --mixed:不删除工作空间改动代码,撤销 commit,并且撤销git add .操作,注意:默认是带有这个参数的。
  • --soft:不删除工作空间改动代码,撤销 commit,不撤销git add .
  • --hard:删除工作空间改动代码,撤销 commit,撤销git add .

再注意:如果对某个文件回退到某个版本,可以选择以下方式,你可能需要配合git log

一、git checkout ${commit} /path/to/file

二、git reset ${commit} /path/to/file

${commit} commit 是你从 git log 中找到某个版本的 hash 字符串

  1. 修改 commit 的注释

有时候,一不小心 commit 了,但是注释不是自己想要的,怎么办?

当然,你可以选择git reset --soft HEAD^

不过,不需要那么麻烦,你可以选择这样的方式:

git commit --amend # vi 编辑器...

log 日志

终端执行:

git log

v6sL77-CDjXPF

嗯,公司 mac 上的 iterm2,透明度有点低...

在这图上,你能看到很多信息

git reflog

o7B2Jo-NbK5Tx

很显然,记录我所有执行 git 命令的操作,可恶...

小结

本文挺长了,不能再写了,要不然会被声讨的...

我个人觉得算是比较详细的讲解了,若是在工作上再碰到其他常用的命令,我出个文章(三)...

感谢大家的观看...

我要悄悄的走了...

参考


司司
1 声望0 粉丝

狠狠做一个努力的人吧