你的文件需要 git,常用命令
上一节主要介绍了
- git 是什么?
- git 能做什么?
- github 是什么?如何注册与简单使用
- git 的配置文件
- git 单用户与多用户的配置
- github page 的简单使用
好了,工具是有了,那么我们就要了解如何使用它来提高我们的效率,甚至解决工作中较常出现的问题。
但凡是个程序员,必须要学会 git 的基本操作,无论是学生时代,还是工作职场,多多少少会点 git 的命令。
嗯,鄙人也是从学生时代正在慢慢跨越到工作中,从以前简单的git push
与git pull
扩展更多其他常用的命令,以免我们在工作上遇到问题不知所措,甚至出现抓狂烦恼的一幕。
不过,我极力推荐一个在线交互式 git 命令学习的网站:https://learngitbranching.js.org/
好了,多余的话也不再多说了,都在酒里...
创建仓库
假如,我们现在想要有一个这样的需求:本地的项目代码想上传到的远程仓库,该如何做?
我们思考一下,本地仓库该如何和远程仓库关联呢?嗯,这是个问题呀
我做了一个这样的实验,我在桌面上创建了一个文件夹: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 上创建一个仓库,如图:
关于如何创建仓库,这里暂时就不说了咩
从图中可以看到
- 远程仓库名为:ss-test
- 如果是新项目,图中很明显教我们如何做
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 # 直接打通桥梁,开始上传
- 如果是已有 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'。
如图所示,我们能看到 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
从上面你可以熟悉几个以下命令:
- git init
- git remote add origin xxx.git
- git add
- git commit -m
- git push --set-upstream origin xxx
上传已有仓库(分支)
假如,我们现在有这么个需求,远程仓库已经有了项目,我们本地仓库想关联远程仓库,但是其他分支,比如 feat_test,那么该如何做
两种情况:
- 没有关联远程仓库,想关联远程仓库,并上传新的分支上,该如何做?
第一步该做什么?那肯定是初始化
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'。
- 你在已有的远程仓库并关联了分支,该如何做?
比如,你从 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'。
从以上你可以了解的命令:
- git checkount -b xxx
- git branch -m xxx
- git branch -a (查看远程所有分支)
我稍微补充一些,如何拉取远程分支
拉取远程分支
- 当然你可以拉取 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
直接拉取远程分支
- 创建文件夹:xxx
- 进入 xxx 文件下,终端输入
git init
- 接着,建立远程仓库连接:
git remote add origin git@xxxx.git
- 拉取远程分支到本地:
git fetch origin xxx(远程分支)
- 拉取远程文件到本地:
git pull origin xxx(远程分支)
- 结束
合并
- 合并 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
- 合并其他分支
git checkout feat_test
git merge feat_test2 --allow-unrelated-histories
注意:如果git checkout feat_test
出现问题,请拉取远程分支到本地仓库,git fetch origin feat_test
- master 合并覆盖分支(冲突),如何解决
那就慢慢解决呗,解决冲突再上传即可
注意:一般公司不会让你随便 merge request...
小插曲:git rebase 和 git merge 的区别
从以上你可以学到的命令:
- git checkout xxx
- git merge xxx --allow-unrelated-histories
删除分支
我们知道仓库有本地和远程,那么在咱们删除分支,不仅要删本地,还要删远程,如何操作?
git branch -d feat_test # 本地
git push origin -d feat_test # 远程
从图上看,远程 feat_test 被删除了
从以上可以学到的命令:
- git branch -d xxx
- 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
注意,这哥们可不能文件回退某个版本
再注意,如果你提交了 add,亦或者 commit 了,那么 checkout 没啥子效果,不信你试试,反正我试过了...嘻嘻嘻
从以上你可以学到的命令:
- git checkout xxx(某个文件,撤销修改)
- git checkout . (撤销所有修改的文件)
但是如果真的 add 了,或者 commit,想回退,咋整?
回退版本
- 修改,无 add,无 commit
git checkout xxx # 回到开始无修改的仓库
- 修改,有 add,无 commit
git restore --staged <file>... # 同上
or
git reset <file>... # 同上
- 修改,有 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 字符串
- 修改 commit 的注释
有时候,一不小心 commit 了,但是注释不是自己想要的,怎么办?
当然,你可以选择git reset --soft HEAD^
不过,不需要那么麻烦,你可以选择这样的方式:
git commit --amend # vi 编辑器...
log 日志
终端执行:
git log
嗯,公司 mac 上的 iterm2,透明度有点低...
在这图上,你能看到很多信息
git reflog
很显然,记录我所有执行 git 命令的操作,可恶...
小结
本文挺长了,不能再写了,要不然会被声讨的...
我个人觉得算是比较详细的讲解了,若是在工作上再碰到其他常用的命令,我出个文章(三)...
感谢大家的观看...
我要悄悄的走了...
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。