Git Study
参考链接
branch
参考链接
在偶尔的情况下,可能会想要保留那些与你的代码没有共同祖先的分支。例如在这些分支上保留生成的文档或者其他一些东西。
如果需要创建一个不使用当前代码库作为父提交的分支,可以用如下的方法创建一个空分支。
方法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到远程仓库。
commit
参考链接
在commit之后修改注释
已经 push
对于已经提交并已经 push 到远程仓库中的需要通过 git rebase
才能完成。
首先要 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一下就搞定了。
git push --force
撤销 commit
在commit之后撤销已经提交的commit
背景
-
代码修改后已经执行了commit和push
-
希望撤销这次commit,回到到这个commit之前的状态:包括本地和远程仓库
操作
找出提交历史记录
先 git log
找出提交的历史记录
比如下面有四个commit记录:
$ git log
commit 87dabb290ae1a4e620512b7cd81d2161747c6ec9
Author: Sky Ao <[email protected]>
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 <[email protected]>
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 <[email protected]>
Date: Thu Jul 21 14:37:19 2016 +0800
change java version to 1.7
commit 4beef3ce6557a41e657c2ee4e19c6156eabd759b
Author: Sky Ao <[email protected]>
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。
其他 :
根据–mixed –soft –hard
,会对 working tree 和 index 和 HEAD 进行重置:
git reset –mixed
:此为默认方式,不带任何参数的git reset,即这种方式,它回退到某个版本,只保留源码,回退 commit 和 index 信息
git reset –soft
:回退到某个版本,只回退了 commit 的信息,不会恢复到 index file 一级。如果还要提交,直接 commit 即可
git reset –hard
:彻底回退到某个版本,本地的源码也会变为上一个版本的内容
HEAD <sha1-commit-hash>
HEAD^
上一次 <commit_id> 每次commit的SHA1值. 可以用 git log 看到,也可以在页面上 commit 标签页里找到.
执行强制的 push 命令
执行 push 命令,注意是需要增加 –force 来强制推送:
$ git push origin HEAD --force
Total 0 (delta 0), reused 0 (delta 0)
To [email protected]: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: 无法推送一些引用到 '[email protected]:foundation/foundation-etcd.git'
此时,需要将当前分支的 Protected 属性暂时去掉。
对于 gitlab,可以进入当前仓库的设置中的 “Protected branches” 一项,将当前 branch 的 protected 临时去掉,等这次 push 完成,再重新设置回 protected 。
合并 commit
有时 commit 太多,而且可能一个 commit 只是提交一个小 bug ,那么合并 commit 势在必行。
第一种
提交最后一个修改的 commit 使用参数,之前的一个 commit 将会合并到这个即将提交的 commit 中来 :
git commit -a --amend -m "my message here"如果之前有一个提交,并且信息为:
git commit -a -m "my last commit message"
则这个 commit message 将不存在。但该commit的信息已经合并到"my message here"中了。
第二种
如果提交了最后的修改 :
$ git reset --soft HEAD^ #或HEAD^意为取消最后commit
$ git commit --amend
把最后一个 commit 合并到前一个提交中去,例如(由上往下读):
git add b.text
git commit -a -m "my message here"
git add a.text
git commit -a -m "my last commit message"
最后存在的将是"my last commit message"。也可后退 n 个,合并到前面第 n+1 个 commit 中去:
$ git reset --soft HEAD~n #后退到第n,我也不清楚具体含义。
$ git commit --amend [-m "new message"]
最方便的是调用 reflog 查看操作历史,找到具体的 commit id ,然后直接 git reset –hard [commit_id] 就回到你要的版本!
merge
更新github上fork的仓库
背景
-
在github上fork了某项目
-
原仓库有新的改动
-
想将原仓库的改动更新到自己fork的仓库
操作过程
同步代码
以netty为例:
-
源地址:[email protected]:netty/netty.git
-
我fork的: [email protected]:skyao/netty.git
按照下面的步骤:
- 为本地仓库增加一个remote, 命名为"upstream":
git remote add upstream git://github.com/dapr/dapr.git
# 或者
git remote add upstream [email protected]: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
tag
参考链接
记录git中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 --delete v2.5
To [email protected]:username/project.git
- [deleted] v2.5
删除远程所有 tag :
git ls-remote origin | cut -f 2 | grep -iv head | xargs git push --delete origin
remote
参考链接
通过set-url解决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地址是
[email protected]:skyao/learning-git.git
[email protected]/skyao/learning-git.git
和前面clone下来时使用的地址仅有一个字符的差异。
解决问题的方法,可以重新用正确的地址再clone一遍。如果已经有commit,则可以使用 remote 的 set-url 子命令直接修改remote的地址:
git remote set-url origin [email protected]:skyao/learning-git.git
sky@B-47WAMD6R-0023 learning-git % git push
Connection to github.com port 22 [tcp/ssh] succeeded!
submodule
参考链接
下载 Project 并初始化 submodule。
# --depth=1 仅限 Project 深度,对于 submodule 无效。
git clone --recurse-submodules --depth=1 [email protected]:keunghin/blogdeploy.git
更新 submodule。
git submodule update --remote --merge