git基本操作
git add
添加文件到暂存区
# 添加某个文件到暂存区,后面可以跟多个文件,以空格区分
git add xxx
# 添加当前更改的所有文件到暂存区。
git add .
复制代码
git commit
# 提交暂存的更改,会新开编辑器进行编辑
git commit
# 提交暂存的更改,并记录下备注
git commit -m "you message"
# 等同于 git add . && git commit -m
git commit -am
# 对最近一次的提交的信息进行修改,此操作会修改commit的hash值
git commit --amend
复制代码
git pull
pull =fetch+merge
# 从远程仓库拉取代码并合并到本地,可简写为 git pull 等同于 git fetch && git merge
git pull <远程主机名> <远程分支名>:<本地分支名>
# 使用rebase的模式进行合并
git pull --rebase <远程主机名> <远程分支名>:<本地分支名>
复制代码
git fetch
与 git pull
不同的是 git fetch
操作仅仅只会拉取远程的更改,不会自动进行 merge 操作。对你当前的代码没有影响
# 获取远程仓库特定分支的更新
git fetch <远程主机名> <分支名>
# 获取远程仓库所有分支的更新
git fetch --all
复制代码
git branch
# 新建本地分支,但不切换
git branch <branch-name>
# 查看本地分支
git branch
# 查看远程分支
git branch -r
# 查看本地和远程分支
git branch -a
# 删除本地分支
git branch -D <branch-nane>
# 重新命名分支
git branch -m <old-branch-name> <new-branch-name>
Workspace:工作区,就是平时进行开发改动的地方,是当前看到最新的内容,在开发的过程也就是对工作区的操作
Index:暂存区,当执行 git add
的命令后,工作区的文件就会被移入暂存区,暂存区标记了当前工作区中那些内容是被 Git 管理的,当完成某个需求或者功能后需要提交代码,第一步就是通过 git add
先提交到暂存区。
Repository:本地仓库,位于自己的电脑上,通过 git commit
提交暂存区的内容,会进入本地仓库。
Remote:远程仓库,用来托管代码的服务器,远程仓库的内容能够被分布在多个地点的处于协作关系的本地仓库修改,本地仓库修改完代码后通过 git push
命令同步代码到远程仓库。
简单案例
-
首先建立一个文件夹作为仓库
mkdir ~workspace/git_repos
-
进入仓库,初始化文件夹,让它成为仓库。任何目录都可通过git init初始化为仓库,不限数量。
~/workspace/git_repos » git init 提示:使用 'master' 作为初始分支的名称。这个默认分支名称可能会更改。要在新仓库中 提示:配置使用初始分支名,并消除这条警告,请执行: 提示: 提示: git config --global init.defaultBranch <名称> 提示: 提示:除了 'master' 之外,通常选定的名字有 'main'、'trunk' 和 'development'。 提示:可以通过以下命令重命名刚创建的分支: 提示: 提示: git branch -m <name> 已初始化空的 Git 仓库于 /Users/pang/workspace/git_repos/.git/
-
创建测试文件README.md,通过git add命令把它放入暂存区
# 或者使用git add . 这两个命令都是把本地文件加载到暂存区,让git知道我们需要跟踪此文件的变动 ~/workspace/git_repos(master*) » git add -A # 通过git status 可以查看状态,如果变为绿色则说明已经加载到暂存区 ~/workspace/git_repos(master*) » git status 位于分支 master 尚无提交 要提交的变更: (使用 "git rm --cached <文件>..." 以取消暂存) 新文件: README.md
-
github或者gitee创建远程仓库
具体参考github~/workspace/git_repos(master*) » git remote add origin https://github.com/xxxx/git_repos.git # origin为远端仓库名字,约定俗成的最好别改 # -u 参数意思是以后就直接git push就行了 不需要特意加远端仓库名字 ~/workspace/git_repos(master*) » git push origin master -u Username for 'https://github.com': xxxx Password for 'https://xxxx@github.com': 枚举对象中: 4, 完成. 对象计数中: 100% (4/4), 完成. 使用 8 个线程进行压缩 压缩对象中: 100% (3/3), 完成. 写入对象中: 100% (4/4), 437 字节 | 437.00 KiB/s, 完成. 总共 4(差异 0),复用 0(差异 0),包复用 0 To https://github.com/xxxx/git_repos.git * [new branch] master -> master 分支 'master' 设置为跟踪来自 'origin' 的远程分支 'master'。
-
克隆远程仓库
# 后面跟新的目录名 ~/workspace/git_repos(master) » git clone https://github.com/xxxx/git_repos.git demo 正克隆到 'demo'... remote: Enumerating objects: 7, done. remote: Counting objects: 100% (7/7), done. remote: Compressing objects: 100% (5/5), done. remote: Total 7 (delta 0), reused 7 (delta 0), pack-reused 0 接收对象中: 100% (7/7), 完成.
-
进入demo目录,修改克隆文件作为测试
~/workspace/git_repos(master*) » cd demo ~/workspace/git_repos/demo(master) » vim README.md # vim README.md # 修改一次看看 #添加暂存区 ~/workspace/git_repos/demo(master*) » git add README.md # 提交修改 ~/workspace/git_repos/demo(master*) » git commit -m "second modify README.md" [master 6541538] second modify README.md 1 file changed, 1 insertion(+), 1 deletion(-) # push到远程仓库 ~/workspace/git_repos/demo(master) » git push README.md
-
回到上一层目录,此时发现远程仓库为新的,本地仓库为旧的,这是使用git pull 拉取远程仓库
~/workspace/git_repos/demo(master) » cd ../ ~/workspace/git_repos(master*) » git pull remote: Enumerating objects: 5, done. remote: Counting objects: 100% (5/5), done. remote: Compressing objects: 100% (2/2), done. remote: Total 3 (delta 0), reused 3 (delta 0), pack-reused 0 展开对象中: 100% (3/3), 286 字节 | 143.00 KiB/s, 完成. 来自 https://github.com/xxxx/git_repos 34dd439..6541538 master -> origin/master 更新 34dd439..6541538 Fast-forward README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) # 发现已经拉取到最新的文件到本地 ~/workspace/git_repos(master*) » cat README.md 修改一次看看
git的分支
head表示最后一次提交的指针
简单案例
# git branch xxx 创建分支
~/workspace/git_repos(master*) » git branch feature1
# git branch 查看分支列表
~/workspace/git_repos(master*) » git branch
# git checkout xxx 切换分支
~/workspace/git_repos(master*) » git checkout feature1
切换到分支 'feature1'
# 在feature1下创建文件,提交暂存区,提交本地仓库
~/workspace/git_repos(feature1*) » touch test.txt
~/workspace/git_repos(feature1*) » git add test.txt
~/workspace/git_repos(feature1*) » git commit -m "add test.txt"
[feature1 8989c72] add test.txt
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 test.txt
# 创建分支feature2
~/workspace/git_repos(feature1*) » git branch feature2
#切换分支feature2
~/workspace/git_repos(feature1*) » git checkout feature2
切换到分支 'feature2'
#由于在feature1下创建的feature2所以feature2可以产看到feature1下的文件
~/workspace/git_repos(feature2*) » cat test.txt
#git checkout -b xxxx 创建并切换分支xxxx
~/workspace/git_repos(feature2*) » git checkout -b feature3
切换到一个新分支 'feature3'
# git branch -d xxx 删除分支xxx
~/workspace/git_repos(feature3*) » git branch -d feature2
已删除分支 feature2(曾为 8989c72)。
# 在feature3下创建文件,提交暂存区,提交本地仓库
~/workspace/git_repos(feature3*) » vim test2.txt
~/workspace/git_repos(feature3*) » git add test2.txt
~/workspace/git_repos(feature3*) » git commit -m "add test2.txt"
[feature3 f47ec0f] add test2.txt
1 file changed, 1 insertion(+)
create mode 100644 test2.txt
# 切换到master分支
~/workspace/git_repos(feature3*) » git checkout master
切换到分支 'master'
您的分支与上游分支 'origin/master' 一致。
# 删除feature3,发现无法直接删除,因为master和feature3没有合并。
# git branch -D xxx 强制删除
~/workspace/git_repos(master*) » git branch -d feature3
error: 分支 'feature3' 没有完全合并。
如果您确认要删除它,执行 'git branch -D feature3'。
# 合并feature3
~/workspace/git_repos(master*) » git merge feature3
更新 6541538..f47ec0f
Fast-forward
test.txt | 0
test2.txt | 1 +
2 files changed, 1 insertion(+)
create mode 100644 test.txt
create mode 100644 test2.txt
#提交到远程仓库
#但此时远程仓库的分支列表除了master分支以外没有其他分支
~/workspace/git_repos(master*) » git push
枚举对象中: 7, 完成.
对象计数中: 100% (7/7), 完成.
使用 8 个线程进行压缩
压缩对象中: 100% (4/4), 完成.
写入对象中: 100% (6/6), 516 字节 | 516.00 KiB/s, 完成.
总共 6(差异 1),复用 0(差异 0),包复用 0
remote: Resolving deltas: 100% (1/1), done.
To https://github.com/xxxx/git_repos.git
6541538..f47ec0f master -> master
#切换到feature1
~/workspace/git_repos(master*) » git checkout feature1
切换到分支 'feature1'
#git push “远程仓库名” “分支名”
#这样提交的话远程仓库就要新分支feature1了
~/workspace/git_repos(feature1*) » git push origin feature1
总共 0(差异 0),复用 0(差异 0),包复用 0
remote:
remote: Create a pull request for 'feature1' on GitHub by visiting:
remote: https://github.com/xxxx/git_repos/pull/new/feature1
remote:
To https://github.com/xxxx/git_repos.git
* [new branch] feature1 -> feature1
# git push origin :feature1 删除分支
~/workspace/git_repos(feature1*) » git push origin :feature1
To https://github.com/xxxx/git_repos.git
- [deleted] feature1
# git push origin feature1:f1 远程仓库添加以f1的命名新分支
~/workspace/git_repos(feature1*) » git push origin feature1:f1
总共 0(差异 0),复用 0(差异 0),包复用 0
remote:
remote: Create a pull request for 'f1' on GitHub by visiting:
remote: https://github.com/xxxx/git_repos/pull/new/f1
remote:
To https://github.com/xxxx/git_repos.git
* [new branch] feature1 -> f1
git rebase
他的作用和 merge 很相似,用于把一个分支的修改合并到当前分支上。如下图所示,下图介绍了经过 rebase 后提交历史的变化情况。
例子:
假设我们现在有2条分支,一个为 master,一个为 feature/1,他们都基于初始的一个提交 add readme 进行检出分支,之后,master 分支增加了 3.js 和 4.js 的文件,分别进行了2次提交,feature/1 也增加了 1.js 和 2.js 的文件,分别对应以下2条提交记录。
此时,切换到 feature/1 分支下,执行 git rebase master
,成功之后,通过 git log
查看记录。
如下图所示:可以看到先是逐个应用了 mater 分支的更改,然后以 master 分支最后的提交作为基点,再逐个应用 feature/1 的每个更改。
merge和rebase区别
不同于 git rebase
的是,git merge
在不是 fast-forward(快速合并)的情况下,会产生一条额外的合并记录,类似 Merge branch 'xxx' into 'xxx'
的一条提交信息。
回滚操作
git reset
git reset master^ # ^代表回退一个版本,回退两个版本就^^,以此类推
git reset master~3 # 一次性回退三个版本
git reset --option 版本号
--mixed:会把暂存区的文件丢弃,不会动工作目录里的文件
--soft:工作目录和暂存区的文件都不会丢弃
--hard:工作目录和暂存区的文件全部丢弃
git revert
撤销某次操作,此次操作之前之后的commit和history都会保留,并且把这次撤销作为一次最新的提交
下面就用一个案例来理解一下这个命令,如下图所示,假设被红框框起来的地方是会引起 bug 的一次提交,在他的提交之后,又进行了2次提交,其中包含了其它同事的提交。
此时想把引起提交的 bug 的干掉,执行 git revert 1121932
,执行操作后,再打开查看日志,如下图所示,可以看到是新增了一条 commit 记录,这个 commit 的产生的 msg 是自动生成的,Revert 开头,后面跟撤回的 commit-msg 信息 之前的 commit 记录并没有消失,此时也达到了代码回退的效果