Git
Git 简介
Git 是一个版本控制工具,可以记录我们每次提交到 Git 中的版本,便于版本控制,以及还有一个重要的功能就是协作开发。
Git 的版本控制是基于树结构的,开始状态只有根节点(空节点),之后每提交一个版本就会在根节点下添加一个节点,同时 HEAD 指针会指向这个节点。默认是在 master
分支上操作,可以创建其他分支多人协作开发,比如 dev
分支,在 dev
分支上开发完成之后再合并到 master
分支上。
Git 命令
1. Git 配置
配置全局用户名和邮箱用于唯一标识一个用户
git config --global user.name tonngw
git config --global user.email xxx@qq.com
配置的信息会存在家目录下 ~/.gitconfig
文件中
不使用 --global
的话则当前信息只在此项目中生效
2. 快速开始
首先创建一个项目文件夹,比如 project
,想让 git
管理这个文件夹里的所有内容。
第一步:git init
进入 project
文件夹,初始化 git 仓库 git init
ls -a
会发现当前目录下多了一个 .git
隐藏文件夹,用 git 管理项目的所有信息都会存在这个文件夹中。哪一天不想让 git 管理项目了,直接删掉就行了。
第二步:git add filename/directory
在 project
下添加内容,比如创建了一个文件 readme.txt
,然后通过 git add readme.txt
将它添加到暂存区,让 git
管理。
git add .
可以将当前文件夹下的所有文件的修改都添加到暂存区中。
第三步:git commit -m "commit message"
将暂存区中的内容提交 / 持久化到本地库。
这就是一个最基本的用 git
管理本地项目的流程。当然代码放到本地说不定哪一天就丢掉,或者想在别的电脑上开发,这时候就需要远程仓库了。
第四步:git remote add origin 远程地址
我们需要先在远程仓库创建一个仓库,如果没有配置 SSH,默认是 https
的地址,推送代码需要输入账号密码授权。为了方便还是用 SSH 可以免密推送,只需将本地公钥配置到远程仓库中就可以了。SSH 配置可以看上一篇笔记
第五步:git push -u origin master
将当前分支(默认是 master
分支)推送到远程仓库,此时刷新远程仓库页面马上就能看到我们的代码。
第一次推送需要 -u
,u - upstream
,指定远程分支上传流 / 将当前本地分支与远程分支进行绑定,让 git
知道默认要推送到哪,之后可以直接 git push
不需要加后面的参数。
其他:git status
,查看当前状态,非常常用,我们每进行一系列操作后都会查看一下当前的状态是否是我们预期的。
3. 查看信息
查看版本信息
git log
:查看当前分支的所有版本,从根节点到 HEAD
的所有版本,HEAD
之后的版本看不到。
git log --pretty=oneline
:将版本信息显示在一行,方便查看,原始的git log
打印的信息比较多,不方便查看。
git reflog
:查看 HEAD
指针的移动历史,即 HEAD
指针所有指向过的版本,这个命令可以看到所有的版本。
git log --stat
:显示 commit 历史,以及每次 commit 发生变更的文件
查看文件差异
git diff # 查看暂存区和工作区的差异
git diff HEAD # 显示工作区与当前分支最新commit之间的差异
查看文件状态
git status
查看暂存区信息
git ls-files
:查看暂存区中的内容
4. 添加文件
添加文件到暂存区
git add [file] # 将指定文件添加到暂存区
git add [dir] # 将指定目录添加到暂存区
git add . # 将当前目录下的所有内容添加到暂存区
5. 代码提交
将暂存区中的内容提交到本地库
# 最常用
git commit -m "message" # 将暂存区中的内容提交到本地库
git commit -m [file] [file2] # 将暂存区中指定的文件提交到本地库
git commit -a # 提交工作区自上次 commit 之后的变化,不能指定 message
git commit -v # 提交时显示所有的 diff 信息
强迫症必备!!!
有时候我们提交了一次,可能就单纯因为提交信息写的不好,想改,怎么办?版本回退一下那你的代码还得再写一遍,不太值得吧。这事用下面的命令就可以轻松解决
# 使用一个新的 commit 替代上一次的提交
# 如果代码没有变化,那仅仅用来修改上一次 commit 的提交信息
git commit --amend -m "message" # amend 修改
写了两个功能,一不小心提交了,现在想把这两个功能分两次提交,可以用下面这个命令
# 重做上一次 commit,仅包含指定的文件
git commit --amend [file] [file2]
6. 版本回滚
git reset --hard HEAD^
或 git reset --hard HEAD~
:将本地库回滚到上一个版本,^
和 ~
都表示上一个,要回退几个版本后面加几。
git reset --hard HEAD^^
:向前回滚两个版本git reset --hard HEAD~100
:向前回滚 100 个版本
当版本比较多的时候我们也不知道回滚几次才是我们想要的版本,此时就需要通过版本号来进行回滚,非常常用。
- 首先通过
git log
查看想要回退到的版本号,取当前版本 hash 值前7
位 或者前6
位都可以。 - 然后
git reset --hard 版本号
:即可回滚到当前版本 - 如果想回退到
HEAD
之后的版本,git log
是看不到版本信息的,可以用git reflog
查看。
7. 恢复删除(暂存区)
恢复 restore
前面说了版本回退,是针对本地库的,这里的恢复是针对暂存区的。
git restore readme.txt
:将尚未加入到暂存区中的修改全部撤销,即将工作区中 readme.txt
文件的状态恢复成暂存区中 readme.txt
文件的状态
git restore --staged readme.txt
: 将 readme.txt
在暂存区的当前版本回退到上一个版本。这里指的版本是在暂存区中的版本。之后再执行 git restore filename
恢复的就是暂存区中上一个版本的内容,加上 --staged
和不加的效果完全不一样。
这里我是这样理解的,我们知道本地库维护着一个版本链,暂存区也维护着一个版本链,当我们将暂存区中的版本持久化到本地库中的时候,本地库的版本链才会更新。
恢复 checkout
# 恢复暂存区的指定文件到工作区
git checkout [file]
# 恢复某个 commit 的指定文件到暂存区和工作区
git checkout [commit] [file]
# 恢复暂存区的所有文件到工作区
git checkout .
移除
当我们不想让 git 管理某个文件时,只需要将它从暂存区中删除即可。
# 让 git 不要管理 readme.txt,和 restore 不一样,一个是从暂存区中删除一个是从暂存区中恢复
git rm --cached readme.txt
8. 分支操作
创建分支
切换分支的时候最好先把当前分支上的修改 commit
,防止与其他分支修改产生冲突
git branch branch-name # 新建分支
git checkout -b branch_name # 新建分支,并切换到当前分支
切换分支
git checkout branch_name # 切换分支
git checkout - # 快速切换到上一个所在的分支
查看分支
git branch # 查看本地所有分支和当前所在分支,* 表示当前所在分支
git branch -r # -r remote 查看所有远程分支
git branch -a # -a all 查看所有分支,包括本地分支和远程分支
删除分支
git branch -d branch_name # 删除分支,要到其他分支下才能删除当前分支
git push -d origin branch_name # 删除远程分支
分支合并
比如现在在 master
分支上,要合并 dev
分支,merge
之后就会将 dev
分支合并到 master
中,默认是 fast-forward
快速合并,即直接修改 HEAD
指针指向了 dev
的最新提交。
如果 merge
的时候出现冲突(当两个分支 / 两个用户都对同一个文件进行了修改),需要手动处理冲突,然后再 git add、git commit
git merge branch_name # 本地分支与本地分支合并,将 branch_name 合并到当前分支上
# 选择一个 commit,合并进当前分支
git cherry-pick [commit]
9. 远程同步
仓库相关
git init # 在当前目录下创建一个 Git 本地仓库
git clone [url] # 将远程仓库下载到本地
将本地仓库与远程仓库关联
git remote add origin [url] # 将本地仓库与远程仓库关联,origin 就是远程仓库的别名
# 修改远程仓库地址
# 方法一:直接修改
git remote origin set-url [url]
# 方法二:先删后改
git remote rm origin
git remote add origin [url]
查看远程仓库信息
git remote -v
推送 push
1、将本地分支推送到远程仓库中
方式一:第一次需要加 -u
,将当前所在分支和远程分支相关联,下次推送直接 git push
就可以默认推送到你刚才设置的分支上了。
git push -u origin branch_name
git push
方式二:每次都指定 origin 和 branch_name
,可以推送任何分支到远程仓库
git push origin branch_name
2、设置本地的 branch_nam
分支对应远程仓库的 branch_name
分支
git push --set-upstream origin branch_name # 和 -u 参数是一样的
# 下次 push,直接
git push
3、删除远程仓库的 branch_name 分支
git push -d origin branch_name
强行推送当前分支到远程仓库,即使有冲突,不建议经常使用,特殊时候救急!
git push origin --force
拉取 pull
将远程分支拉取到本地仓库中
方式一:先将远程的 branch_name1
分支与本地的 branch_name2
分支对应。
git branch --set-upstream-to=origin/branch_name1 branch_name2
然后使用
git pull
从设置的远程分支上拉取代码,并将远程仓库的当前分支与本地仓库的当前分支合并。
方式二:指定 origin 和 branch_name
,可以拉取远程任何分支上的内容到本地仓库中,并将远程仓库的 branch_name
分支与本地仓库的当前分支合并。
git pull origin branch_name
方式三:使用下面命令也可以将远程的 branch_name
分支拉取到本地
git checkout -t origin/branch_name
10. Stash 操作
Stash 是一个栈,用于存储当前工作区和暂存区还未提交的修改
应用场景:比如现在我们正在某个分支下编写代码,此时线上服务器出现了故障,领导让你赶紧去修复一下,你需要新开一个分支去解决线上的 bug
,那么现在有两个选择:
- 将当前分支下的修改
git add、git commit
,然后再去维护 bug - 刚写了一点,还没实现一个完整的功能,你还不想马上就提交到本地库,此时就可以使用
Stash
将我们目前工作区和暂存区中未提交的修改添加进去。等处理完线上问题再把刚才的工作从Stash
中弹出来继续工作~
git stash # 将工作区和暂存区中未提交的修改存入栈中
git stash apply # 将栈顶存储的修改恢复到当前分支,但不删除栈顶元素
git stash drop # 删除栈顶存储的修改
git stash pop # 将栈顶存储的修改恢复到当前分支,同时删除栈顶元素
git stash list # 查看栈中所有元素
参考资料
- AcWing Linux 基础课
- https://gitee.com/all-about-git
- git cherry-pick 教程
- 推荐视频:TheCW,还有他的 Vim 也值得一看,很赞!
作业代码
这次作业太舒服了,one pass
很过瘾,y 总讲的太好了~
homework_0
mkdir homework
git init
homework_1
vim readme.txt
i
111 # 添加内容
:wq
git add .
git commit -m "111"
homework_2
vim readme.txt
G
o
222
:wq
git add .
git commit -m "222"
homework_3
mkdir problem1 problem2
cd problem1
# 复制代码
vim main.cpp
:set paste
Shift + Insert
# 检查代码是否正确
:wq
cd problem2
# 复制代码
vim main.cpp
:set paste
Shift + Insert
# 检查代码是否正确
:wq
cd .. # 回到 homework 目录
git add .
git commit -m "add main.cpp"
homework_4
rm -r problem2
mkdir problem3
cd problem3
touch main.cpp
# 复制代码
:set paste
Shift + Insert
:wq
cd .. # 回到 homework 目录
vim readme.txt
G
dd
o
333
:wq
git add .
git commit -m "333"
homework_5
# 云端创建 homework 仓库,不要选创建生成 README.md 文件
# 复制远程仓库地址
git remote add origin git@git.acwing.com:tonngw/homework.git # 让本地与远程建立关联
git push -u origin master # 推送到远程 master 分支
homework_6
git checkout -b dev
vim readme.txt
G
o
444
:wq
git add .
git commit -m "444"
git push --setupstream origin dev # 将本地分支推送远程分支
homework_7
git checkout master
vim readme.txt
G
o
555
:wq
git add .
git commit -m "555"
homework_8
git merge dev
# 手动处理冲突,会提示 readme.txt 文件有冲突
vim readme.txt
# 删除注释
:wq
git add .
git commit -m "fix conflicts"
homework_9
git push # 将本地 master 分支推送到远程仓库
# 登录 myserver 服务器,创建文件夹
# 克隆仓库
git clone git@git.acwing.com:tonngw/homework.git