MENU

必备 git 技能

绝大多数人对于 git的认识只停留在git status, git add, git push, git pull, 好一点会知道git merge, 那就是全部了。

试试以下问题:

  • git push origin master命令中,origin 代表的是什么,整个命令是什么意思,origin 可以修改不
  • git fetch origingit rebase origin master 这些命令知道吗?跟 git merge 有什么区别?
  • git如何合并两个补丁,对第三个补丁进行修改?这个很重要,因为你不会才导致 git commit 的信息没有意义,commit 不够小和多
  • 你试过合并commit 吗?commit message 写的不好时如何修改?如何改变 commit 的顺序?

如果以上有不清楚的话,那么以下的内筒应该对你有帮助。


Github 初始化

初始创建一个 github 仓库时,github 会给一些命令你去创建 git本地项目,git init就不用说了,

git remote add origin git@github.com:cyea/test.git

你知道这里的 origin 是什么吗?

是的,就仅仅是一个名字,对git@github.com:cyea/test.git 这个 ssh 地址的命名,你可以把origin命名为 other

git remote add other git@github.com:cyea/test.git

以后就可以用

git push gakki master

另外,你还可以add好几个名字.

比如:你在 github 跟coding 同样都有仓库放代码的情况。

git push -u origin master
# 这里就是把 master(默认 git 分支)推送到 origin
#  -u 也就是 --set-upstream , 代表的是更新默认推送的地方,
# 这里就是默认以后 git pull 和 git push 时,都是推送和拉自 origin 

有意义的 commit

对于 git 工作流,我认为·commit 数要多而有意义,branch 也要多而有意义——也就是,一个小功能就要开一个分支,一个分支里要有一些有意义的 commit。 好处就是冲突会很少,review 代码速度加快,commit 都是有意义的,而且利于回退。

要做到这些,离不开掌握git rebase

永远使用 rebase

git rebase

Reapply commits from one branch on top of another branch.
Commonly used to "move" an entire branch to another base, creating copies of the commits in the new location.

相信你可以理解以上的英文:把 A 分支rebase 到 B 分支,也就是把 A 的 commit 与 B 的合并,并且保留 B 独特的 commit。

还是很抽象,对吧?

看一个例子:git pull origin feat-add 这里就是把 origin仓库拉到 feat-add分支。实际上,所做的东西等价于:

git fetch origin          //把 origin 仓库的东西都拉下来本地
git merge origin/master feat-add //把 origin 的 master 分支 merge 到 feat-add

因为 pull 的时候, 当出现冲突而你解决掉后,会有多余的merge信息(commit message)

所以我是推荐在自己的分支开发时,使用git fetch origin 以及 git rebase origin/master feat-add,这样不会出现多余信息,处理冲突更加自由

这两条命令的合并版就是

git pull -r origin/master feat-add
# -r意思是在 pull 的时候,使用 rebase.

合并 commits

Author: cyea <yuyehack@gmail.com>
Date:   Tue Aug 13 15:11:56 2019 +0800

    asd

commit c25e0b088741f143848d78613038056d0414df64 (origin/feature-1.0, feature-1.0)
Author: cyea <yuyehack@gmail.com>
Date:   Fri Aug 9 18:05:59 2019 +0800

    fix

commit 15c0f38a8747d404f6476614c8d639979e83ff4e
Author: cyea <yuyehack@gmail.com>
Date:   Fri Aug 9 17:56:22 2019 +0800

    fix

commit 29c0ae64ee3e443338ae07dca0db41ef1fbec168

假设你又以上三个 commit,如何合并,修改呢? git rebase -i HEAD~4 对前四个补丁就行修改,就会进入以下界面:

pick 4b7061d map
pick 26de848 orderdetail
pick 15c0f38 fix
pick c25e0b0 fix
pick 654daac asd

# Rebase fb0aeba..654daac onto fb0aeba (5 commands)
#
# Commands:
# p, pick <commit> = use commit
# r, reword <commit> = use commit, but edit the commit message
# e, edit <commit> = use commit, but stop for amending
# s, squash <commit> = use commit, but meld into previous commit
# f, fixup <commit> = like "squash", but discard this commit's log message
# x, exec <command> = run command (the rest of the line) using shell
# d, drop <commit> = remove commit
# l, label <label> = label current HEAD with a name
# t, reset <label> = reset HEAD to a label
# m, merge [-C <commit> | -c <commit>] <label> [# <oneline>]
# .       create a merge commit using the original merge commit's
# .       message (or the oneline, if no original merge commit was
# .       specified). Use -c <commit> to reword the commit message.
#
# These lines can be re-ordered; they are executed from top to bottom.
#
# If you remove a line here THAT COMMIT WILL BE LOST.
#
#       However, if you remove everything, the rebase will be aborted.
#
#       
# Note that empty commits are commented out
~

有以下常用操作:

  • 默认pick, 不做更改
  • reword:改 commit message
  • squash:当前补丁跟上一个补丁合并
  • fixup: 跟 squash 作用一样,但是会丢弃当前 commit 信息,使用上一个的;squash 则是可以让你重新写

需要修改时,把上面四个补丁最前面的 pick 改成对应操作(如 reword,fixup),然后保存退出即可。


回退

回退大家应该都知道git reset --hard commitID, 把整个 git 回退到这个 commitID 里;

其实除了--hard, 还有 soft.

hard是把改动全部都丢弃,而soft则柔软一些,仅仅是把所做的 commit 丢掉,而改动都保留在本地——通常用来修改,再重新 commit 一遍。

做了胡乱的更改,导致 git log都不正常,找不回那个 commit 了怎么办?

不用担心, 还有 git reflogReference logs, or "reflogs", record when the tips of branches and other references were updated in the local repository.

用它可以看到你对当前项目所做过的所有 git 操作,所有 git 操作的 id 号——意味着你可以回退到任意的时刻。

所以,只要你没有把改动没有做 commit 就丢失,又或者用git push -f把 github 仓库覆盖了,你就可以恢复任意时刻的东西。


git stash 暂存更改

时刻要注意,当前修改没有 commit 的时候,不能 checkout 切换分支。

此时不想 commit,便需要 git stash 暂存更改;顾名思义,stash 使用 stack(栈)实现,所以可以 git stash存多次,然后切换分支后, git stash pop 撤出来

比 grep 更好用的 git grep

相比于 grep -R keyword ./ , 我是更喜欢用 git grep keyword, 差不多是一样的,不过git grep只是会找当前的 目录中git 有 track(跟踪)的文件【也就是变动时,git status 会检测到变化的文件】


超级进阶:分割commit

 Author: cyea <yuyehack@gmail.com>
Date:   Tue Aug 13 15:11:56 2019 +0800

    asd

commit c25e0b088741f143848d78613038056d0414df64 (origin/feature-1.0, feature-1.0)
Author: cyea <yuyehack@gmail.com>
Date:   Fri Aug 9 18:05:59 2019 +0800

    fix

commit 15c0f38a8747d404f6476614c8d639979e83ff4e
Author: cyea <yuyehack@gmail.com>
Date:   Fri Aug 9 17:56:22 2019 +0800

    fix

commit 29c0ae64ee3e443338ae07dca0db41ef1fbec168

假设我们想要分割 15c0f38a8747d404f6476614c8d639979e83ff4e. 这个 commit,可以直接使用

git rebase -i HEAD~7 #(数字随意,反正在 Unlink 这个 commit 前就可以了)

选择 Unlink 这个 commit, 改成 edit。 一般情况下,就是这样修改 commit 的,修改后再 git rebase –continue.

但是,我们需要的是分割补丁: 选择 git rebase HEAD^, 撤销这次 commit,再把想改动的文件 git add, 再 git commit, 这样就可以分割很多补丁。

最后,git rebase –continue 就可以了。

Archives Tip
QR Code for this page
Tipping QR Code