Git Study

参考链接

git-docs

Git学习笔记

Become a git guru.

git-stash

参考链接

How to Delete a Git Branch Both Locally and Remotely

在偶尔的情况下,可能会想要保留那些与你的代码没有共同祖先的分支。例如在这些分支上保留生成的文档或者其他一些东西。

如果需要创建一个不使用当前代码库作为父提交的分支,可以用如下的方法创建一个空分支。

执行以下git命令:

sh

git symbolic-ref HEAD refs/heads/newbranch
rm .git/index
git clean -fdx
<do work>
git add your files
git commit -m 'Initial commit'

这里以github的操作为例,下面试图创建一个名为gh-pages的空分支:

sh

$ cd repo

$ git checkout --orphan gh-pages
# 创建一个orphan的分支,这个分支是独立的
Switched to a new branch 'gh-pages'

$ git rm -rf .
# 删除原来代码树下的所有文件
rm ......

注意这个时候用git branch命令是看不见当前分支的名字的,除非进行了第一次commit。

下面我们开始添加一些代码文件,例如这里新增了一个index.html:

sh

$ echo \"My GitHub Page\" > index.html
$ git add .
$ git commit -a -m \"First pages commit\"
$ git push origin gh-pages

在commit操作之后,你就可以用git branch命令看到新分支的名字了,然后push到远程仓库。


参考链接

git 删除错误提交的commit

git commit 合并

Delete Local Commits in Git

在commit之后修改注释

对于已经提交并已经 push 到远程仓库中的需要通过 git rebase 才能完成。

首先要 git rebase 到需要修改的那个 commit 的前1个 commit。假设 commit id 是 32e0a87f,运行下面的 git rebase 命令:

sh

git rebase -i 32e0a87f

在 git bash 中运行上面的命令后,会弹出编辑框,在编辑框中会分行依次显示以 pick 开头的这个 commit 之后的所有 commit message。

将需要修改的commit message之前的"pick"改为"reword",点击保存按钮,并关闭编辑框,这时会执行rebase操作。

Rebasing (1/3)

接着会再次弹出编辑框,这次编辑框中只有之前改为"reword"的那个commit message,此时修改commit message的内容,点击保存按钮并关闭编辑框,会继续执行rebase操作。

如果操作成功,会出现如下的提示:

sh

[detached HEAD aa3b52c] Add return url
 2 files changed, 1 insertion(+), 3 deletions(-)
Successfully rebased and updated refs/heads/oss.

这样就完成了git commit message的修改,然后强制push一下就搞定了。

sh

git push --force

在commit之后撤销已经提交的commit

  • 代码修改后已经执行了commit和push

  • 希望撤销这次commit,回到到这个commit之前的状态:包括本地和远程仓库

git log 找出提交的历史记录

比如下面有四个commit记录:

sh

$ 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

sh

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 命令,注意是需要增加 –force 来强制推送:

sh

$ 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后面指定远程分支的名字,如:

sh

git push origin HEAD:learning --force

如果当前分支是 protecded 的受保护分支,则 git 服务器会拒绝强制推送,报错如下:

sh

$ 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 只是提交一个小 bug ,那么合并 commit 势在必行。

提交最后一个修改的 commit 使用参数,之前的一个 commit 将会合并到这个即将提交的 commit 中来 :

sh

git commit -a --amend -m "my message here"如果之前有一个提交,并且信息为:
git commit -a -m "my last commit message"

则这个 commit message 将不存在。但该commit的信息已经合并到"my message here"中了。

如果提交了最后的修改 :

sh

$ git reset --soft HEAD^ #或HEAD^意为取消最后commit
$ git commit --amend

把最后一个 commit 合并到前一个提交中去,例如(由上往下读):

sh

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 中去:

sh

$ git reset --soft HEAD~n #后退到第n,我也不清楚具体含义。
$ git commit --amend [-m "new message"]

最方便的是调用 reflog 查看操作历史,找到具体的 commit id ,然后直接 git reset –hard [commit_id] 就回到你要的版本!


更新github上fork的仓库

  • 在github上fork了某项目

  • 原仓库有新的改动

  • 想将原仓库的改动更新到自己fork的仓库

以netty为例:

按照下面的步骤:

  1. 为本地仓库增加一个remote, 命名为"upstream":

sh

git remote add upstream git://github.com/dapr/dapr.git
# 或者
git remote add upstream [email protected]:dapr/dapr.git

也有人推荐下面的多了–track参数的的方式:

sh

git remote add --track master upstream git://github.com/dapr/dapr.git
  1. fetch 这个upstream远程的所有分支到remote-tracking分支, 例如upstream/master

sh

git fetch upstream
  1. 确认当前分支是master分支, 如果不是checkout到master分支

sh

git branch
git checkout master
  1. 同步upstream的修改到本地, 可以选择rebase或者merge

sh

git rebase upstream/master
git merge upstream/master

注: 推荐用merge.

  1. 将更新之后的版本推送到自己fork的仓库

sh

git push -f origin master

sh

git fetch upstream --tags

git push --tags

参考链接

2.6 Git Basics - Tagging

How to delete local and remote git tags (WITH EXAMPLES)

Remove all git tags

How To Delete Local and Remote Tags on Git

记录git中tag命令的用法。

sh

git tag
git tag -l 'v1.4.2.*'

添加轻量级标签:

sh

git tag -a v1.4

添加含附注类型的标签:

sh

git tag -a v1.4 -m 'my version 1.4'

推送到远程:

sh

git push origin v1.4

或者 –tags 推送全部:

sh

git push --tags

删除本地 tag :

sh

git tag -d v1.0.0

删除远程指定 tag :

sh

$ git push origin --delete v2.5
To [email protected]:username/project.git
 - [deleted]               v2.5

删除远程所有 tag :

sh

git ls-remote origin | cut -f 2 | grep -iv head | xargs git push --delete origin

参考链接

Git Bash: remote error: You can’t push to git://github.com

通过set-url解决can’t push错误

如果clone时 remote 的地址信息有问题,比如通过 git clnoe git://github.com/skyao/learning-git.git 的方式 clone 下来的仓库,在改动之后push时,会报错,错误信息如下:

sh

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地址是

sh

[email protected]:skyao/learning-git.git
[email protected]/skyao/learning-git.git

和前面clone下来时使用的地址仅有一个字符的差异。

解决问题的方法,可以重新用正确的地址再clone一遍。如果已经有commit,则可以使用 remote 的 set-url 子命令直接修改remote的地址:

sh

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!

参考链接

Git-Tools-Submodules

下载 Project 并初始化 submodule。

sh

# --depth=1 仅限 Project 深度,对于 submodule 无效。
git clone --recurse-submodules --depth=1 [email protected]:keunghin/blogdeploy.git

更新 submodule。

sh

git submodule update --remote --merge