Git命令
- 1: branch命令
- 2: checkout命令
- 3: commit命令
- 4: merge命令
- 4.1: 更新fork仓库
- 5: tag命令
- 5.1: tag命令用法
- 6: remote命令
- 6.1: 解决can't push错误
1 - branch命令
1.1 - 创建空白分支
在偶尔的情况下,可能会想要保留那些与你的代码没有共同祖先的分支。例如在这些分支上保留生成的文档或者其他一些东西。
如果需要创建一个不使用当前代码库作为父提交的分支,可以用如下的方法创建一个空分支。
方法1
执行以下git命令:
git symbolic-ref HEAD refs/heads/newbranch
rm .git/index
git clean -fdx
<do work>
git add your files
git commit -m 'Initial commit'
方法2
这里以github的操作为例,下面试图创建一个名为gh-pages的空分支:
$ cd repo
$ git checkout --orphan gh-pages
# 创建一个orphan的分支,这个分支是独立的
Switched to a new branch 'gh-pages'
$ git rm -rf .
# 删除原来代码树下的所有文件
rm ......
添加内容并push
注意这个时候用git branch命令是看不见当前分支的名字的,除非进行了第一次commit。
下面我们开始添加一些代码文件,例如这里新增了一个index.html:
$ echo \"My GitHub Page\" > index.html
$ git add .
$ git commit -a -m \"First pages commit\"
$ git push origin gh-pages
在commit操作之后,你就可以用git branch命令看到新分支的名字了,然后push到远程仓库。
1.2 - 重命名分支
本地操作
在本地 clone 好仓库之后, 执行分支的重命名操作, 如将默认分支从 mater 重命名为 main, 则需要执行如下命令:
# 确认在 master 分支上
# git checkout master
# 1. 本地进行分支重命名: master -> main
git branch -m main
# 2. 删除远程仓库的旧分支
git push origin --delete master
# 3. 推送新分支到远程仓库
git push origin -u main
对于其他位置 clone 的本地仓库, 则需要更新本地仓库:
# 获取最新变更
git fetch origin
# 删除本地旧分支
git branch -d master
# 切换到新分支并建立跟踪
git checkout --track origin/main
备注: 使用的
-m是--move的简写
github上操作
在 github 页面上操作重命名分支,如将默认分支从 mater 重命名为 main, 对于本地已经 clone 的仓库,则需要执行如下命令:
git branch -m master main
git fetch origin
git branch -u origin/main main
git remote set-head origin -a
2 - checkout命令
从上流分支checkout
在不产生任何合并(Merge)和冲突的情况下,把 upstream(上游原仓库)的分支如 dev “搬”到个人 fork 仓库中。
先检查是否正确设置了 upstream:
git remote -v
如果没有,则通过命令添加 upstream:
git remote add upstream <原仓库的URL>
拉取 upstream 的信息:
git fetch upstream
基于远程 dev 分支创建本地 dev 分支:
git checkout -b dev upstream/dev
然后推动到自己的 fork 仓库:
git push -u origin dev
备注: -u 参数的意思是建立追踪关系,以后在本地的 dev 分支上执行 git push 或 git pull 时,Git 就会默认对应到 fork 仓库里的 dev 分支。
3 - commit命令
3.1 - 修改注释
已经 commit 但还没有 push
最近的一次commit
如果要修改 message 的是最近的一次 commit,则会简单很多,只要简单执行下面的命令修改:
git commit --amend -m "new commit message"
多条commit
如果要修改 message 的提交有多条,或者不是最新的一条,则要交互式变基(Interactive Rebase)。
先通过 git log 命令确认要修改 message 的 commit,比如是要修改倒数第3次的 commit,则可以执行:
git rebase -i HEAD~3
或者 git rebase 到需要修改的那个 commit 的前1个 commit。假设 commit id 是 32e0a87f,运行下面的git rebase 命令:
git rebase -i 32e0a87f
在 git bash 中运行上面的命令后,会弹出编辑框,在编辑框中会分行依次显示以 pick 开头的这个 commit 之后的所有 commit message。
将需要修改的 commit message 之前的 “pick” 改为 “reword”,点击保存按钮,并关闭编辑框,这时会执行rebase操作。
Rebasing (1/3)
接着会再次弹出编辑框,这次编辑框中只有之前改为 “reword” 的那个 commit message,此时修改 commit message 的内容,点击保存按钮并关闭编辑框,会继续执行 rebase 操作。
如果操作成功,会出现如下的提示:
[detached HEAD aa3b52c] Add return url
2 files changed, 1 insertion(+), 3 deletions(-)
Successfully rebased and updated refs/heads/oss.
这样就完成了 git commit message 的修改,然后强制 push 一下就搞定了。注意可以一次性修改多条 commit,只要把多条 commit 之前的 “pick” 改为 “reword” 即可。
已经push到git仓库
修改 message 的方式是一样的,但是修改完之后需要强推才能覆盖远程仓库。
修改完成之后强推到 git 仓库:
# 如果是自己的仓库或者分支,不会有冲突问题,简单 --fore 即可
git push --force
# 如果是多人合作的仓库或者分支,需要使用更安全的版本:
git push --force-with-lease
关于 --force 和 --force-with-lease 的区别:
--force:直接用本地的分支覆盖远程分支--force-with-lease:在覆盖前会检查一下远程分支有没有被别人提交了新代码。如果有新代码,强推会被拒绝,避免误删。
3.2 - 撤销commit
背景
- 代码修改后已经执行了commit和push
- 希望撤销这次commit,回到到这个commit之前的状态:包括本地和远程仓库
操作
找出提交历史记录
先 git log 找出提交的历史记录
比如下面有四个commit记录:
$ git log
commit 87dabb290ae1a4e620512b7cd81d2161747c6ec9
Author: Sky Ao <aoxiaojian@gmail.com>
Date: Thu Jul 21 16:36:26 2016 +0800
add cliet builder and wrap native api; setup integration test; add first unit test case and integration test case
commit 6899dd19dbe58da6ae65fd157a791151967c16b2
Author: Sky Ao <aoxiaojian@gmail.com>
Date: Thu Jul 21 15:17:00 2016 +0800
rollback package name to etcdserverpb, otherwise etcd server will reject the request
commit 18d034b3a1e20e81ece3d2f6ba9919e8bdb3dfd4
Author: Sky Ao <aoxiaojian@gmail.com>
Date: Thu Jul 21 14:37:19 2016 +0800
change java version to 1.7
commit 4beef3ce6557a41e657c2ee4e19c6156eabd759b
Author: Sky Ao <aoxiaojian@gmail.com>
Date: Wed Jul 20 18:40:18 2016 +0800
现在需要撤销最新的这一次 87dabb290ae1a4e620512b7cd81d2161747c6ec9 提交, 回退到它的上一次 6899dd19dbe58da6ae65fd157a791151967c16b2。
执行 reset 命令
git reset --hard 6899dd19dbe58da6ae65fd157a791151967c16b2
HEAD 现在位于 6899dd1 rollback package name to etcdserverpb, otherwise etcd server will reject the request
注意 commitid 是要撤销的commit的前一次commit的id,也就是说 reset 命令是将提交 重置 到要撤销的前一次。
reset命令执行完成后,本地仓库就重置,相当于撤销了 6899dd1 之前的所有commit。
执行强制的 push 命令
执行 push 命令,注意是需要增加 –force 来强制推送:
$ git push origin HEAD --force
Total 0 (delta 0), reused 0 (delta 0)
To git@github.com:skyao/jetcd.git
+ 87dabb2...6899dd1 HEAD -> master (forced update)
push 命令执行完成,远程仓库也就重置了。此时从远程仓库上看,在这次 6899dd19dbe58da6ae65fd157a791151967c16b2 提交之后的所有commit已经消失,相当于 git 仓库回滚到这个提交了。
如果不是master branch,则需要在HEAD后面指定远程分支的名字,如:
git push origin HEAD:learning --force
处理受保护分支
如果当前分支是 protecded 的受保护分支,则 git 服务器会拒绝强制推送,报错如下:
$ git push origin HEAD --force
Total 0 (delta 0), reused 0 (delta 0)
remote: GitLab: You are not allowed to force push code to a protected branch on this project.
To basiccloud.net:foundation/foundation-etcd.git
! [remote rejected] HEAD -> master (pre-receive hook declined)
error: 无法推送一些引用到 'git@basiccloud.net:foundation/foundation-etcd.git'
此时,需要将当前分支的 Protected 属性暂时去掉。
对于 gitlab,可以进入当前仓库的设置中的 “Protected branches” 一项,将当前 branch 的 protected 临时去掉,等这次 push 完成,再重新设置回 protected 。
参考资料
4 - merge命令
4.1 - 更新fork仓库
背景
- 在github上fork了某项目
- 原仓库有新的改动
- 想将原仓库的改动更新到自己fork的仓库
操作过程
同步代码
以netty为例:
- 源地址:git@github.com:netty/netty.git
- 我fork的: git@github.com:skyao/netty.git
按照下面的步骤:
-
为本地仓库增加一个remote, 命名为"upstream":
git remote add upstream git://github.com/dapr/dapr.git # 或者 git remote add upstream git@github.com:dapr/dapr.git也有人推荐下面的多了–track参数的的方式:
git remote add --track master upstream git://github.com/dapr/dapr.git -
fetch 这个upstream远程的所有分支到remote-tracking分支, 例如upstream/master
git fetch upstream -
确认当前分支是master分支, 如果不是checkout到master分支
git branch git checkout master -
同步upstream的修改到本地, 可以选择rebase或者merge
git rebase upstream/master git merge upstream/master注: 推荐用merge.
-
将更新之后的版本推送到自己fork的仓库
git push -f origin master
同步tag
git fetch upstream --tags
git push --tags
参考资料
5 - tag命令
5.1 - tag命令用法
记录git中tag命令的用法。
tag命令用法
列出已有tag
git tag
git tag -l 'v1.4.2.*'
添加tag
添加轻量级标签:
git tag -a v1.4
添加含附注类型的标签:
git tag -a v1.4 -m 'my version 1.4'
推送到远程:
git push origin v1.4
或者–tags推送全部:
git push --tags
删除tag
删除本地tag:
git tag -d v1.0.0
删除远程tag:
git push origin :refs/tags/v1.0.0
资料
git官方资料
中英文两个版本:
6 - remote命令
6.1 - 解决can't push错误
如果clone时 remote 的地址信息有问题,比如通过 git clnoe git://github.com/skyao/learning-git.git 的方式 clone 下来的仓库,在改动之后push时,会报错,错误信息如下:
git push
fatal: 远程错误:
You can't push to git://github.com/skyao/learning-git.git
Use https://github.com/skyao/learning-git.git
事实上,在github 页面上,给出的clone地址是
git@github.com:skyao/learning-git.git
git@github.com/skyao/learning-git.git
和前面clone下来时使用的地址仅有一个字符的差异。
解决问题的方法,可以重新用正确的地址再clone一遍。如果已经有commit,则可以使用 remote 的 set-url 子命令直接修改remote的地址:
git remote set-url origin git@github.com:skyao/learning-git.git
sky@B-47WAMD6R-0023 learning-git % git push
Connection to github.com port 22 [tcp/ssh] succeeded!