git入门

image.png

1. git commit --amend

有时你提交过代码之后,发现一个地方改错了,
你下次提交时不想保留上一次的记录;
或者你上一次的commit message的描述有误,
这时候你可以使用接下来的这个命令:git commit --amend
该操作会改变你原来的commit id

2. cherry-pick vs rebase vs merge

2.1. merge
merge合并

image.jpeg
那么git merge topic命令将会把在master分支上二者共同的节点
(E节点)之后分离的节点(即topic分支的A B C节点)重现在master分支上,
直到topic分支当前的commit节点(C节点),并位于master分支的顶部。
并且沿着master分支和topic分支创建一个记录
合并结果的新节点,该节点带有用户描述合并变化的信息
2.2. cherry-pick
对于多分支的代码库,将代码从一个分支转移到另一个分支是常见需求。
这时分两种情况。一种情况是,你需要另一个分支的所有代码变动,那么就采用合并(git merge)。
另一种情况是,你只需要部分代码变动(某几个提交),这时可以采用 Cherry pick。
    a - b - c - d   Master
         \
           e - f - g Feature
  • git cherry-pick 分支
  • git cherry-pick
  • git cherry-pick
  • git cherry-pick A..B
2.3. rebase

概念:git rebase你其实可以把它理解成是重新设置基线,将你的当前分支重新设置开始点。这个时候才能知道你当前分支于你需要比较的分支之间的差异。

image.png

1.  master  1-2-3 是现在的分支状态
2. 这个时候从master ,checkout出来一个prod分支
3. 然后master提交了4.5,prod提交了6.7
4. 这个时候master分支状态就是1-2-3-4-5,prod状态变成1-2-3-6-7
5. 如果在prod上用rebase master ,prod分支状态就成了1-2-3-4-5-6-7
6. 如果是merge 会出来一个8,这个8的提交就是把4-5合进来的提交

好处:提交直观 便于回退 拉取代码有预处理阶段 不用生成新的节点
注意:不要通过rebase对任何已经提交到公共仓库中的commit进行修改

  • git pull --rebase
  • git rebase -i [startpoint] [endpoint]
    git rebase [startpoint] [endpoint] --onto [branchName]
  • git rebase -i HEAD~n
pick:保留该commit(缩写:p)
reword:保留该commit,但我需要修改该commit的注释(缩写:r)
edit:保留该commit, 但我要停下来修改该提交(不仅仅修改注释)(缩写:e)
squash:将该commit和前一个commit合并(缩写:s)
fixup:将该commit和前一个commit合并,但我不要保留该提交的注释信息(缩写:f)
exec:执行shell命令(缩写:x)
drop:我要丢弃该commit(缩写:d)

3. 什么是 HEAD

3.1 概念:

Git 中的 HEAD 可以理解为一个指针,我们可以在命令行中输入 cat .git/HEAD 查看当前 HEAD指向哪儿,一般它指向当前工作目录所在分支的最新提交或者分支。

切换分支时,HEAD 会移动到指定分支

3.2 HEAD游离状态

使用的是 git checkout < commit id>,即切换到指定的某一次提交,HEAD就会处于 detached状态(游离状态)

HEAD 处于游离状态时,我们可以很方便地在历史版本之间互相切换,比如需要回到
某次提交,直接 checkout 对应的 commit id 或者 tag 名即可。
它的弊端就是:在这个基础上的提交会新开一个匿名分支!
HEAD 就会处于 detached 状态
可以看到,我还没有修改和提交的情况下,切换完成就给我新建了一个分支,并且指明 HEAD 
正游离在 2772886 的  上。
如果不做任何修改,想回到 master 分支,直接 git checkout master 即可,
而不要 checkout master 主干所对应的 。
顺利回到主干的话,HEAD 的游离状态会取消,原临时游离分支也会消失。
如果是在游离状态做了修改和提交,则:
切换会 master 分支时,在游离状态所做的修改和提交无法追溯
3.3 git reset [--soft | --mixed | --hard] HEAD^
  • --mixed 为默认,可以不用带该参数,用于重置暂存区的文件与上一次的提交(commit)保持一致,工作区文件内容保持不变。
$ git reset HEAD^            # 回退所有内容到上一个版本  
$ git reset HEAD^ hello.php  # 回退 hello.php 文件的版本到上一个版本  
$ git  reset  052e           # 回退到指定版本
  • --soft 参数用于回退到某个版本 保留工作目录,并把重置 HEAD 所带来的新的差异放进暂存区
    image.png
什么是「重置 HEAD 所带来的新的差异:
由于 HEAD 从 4 移动了 3,而且在 reset 的过程中工作目录和暂存区的内容没有被清理掉,
所以 4 中的改动在 reset 后就也成了工作目录新增的「工作目录和 HEAD 的差异」。
这就是上面一段中所说的「重置 HEAD 所带来的差异」
  • --hard 参数撤销工作区中所有未提交的修改内容,将暂存区与工作区都回到上一次版本,并删除之前的所有信息提交:
$ git reset –hard HEAD~3  # 回退上上上一个版本  
$ git reset –hard bae128  # 回退到某个版本回退点之前的所有信息。 
$ git reset --hard origin/master    # 将本地的状态回退到和远程的一样 
注意:谨慎使用 –hard 参数,它会删除回退点之前的所有信息。

4 Gerrit 的 Change-Id

Change-Id 是 gerrit (代码审核平台)的概念

image.png

  • Change-Id的生成
Gerrit 提供了标准的“commit-msg”钩子来实现。
Git 提供了4个提交工作流钩子:pre-commit、prepare-commit-msg、
commit-msg、post-commit。其中 commit-msg 钩子,
会在我们执行 git commit 时被执行。
本质上,commit-msg 钩子是一段脚本程序,放在 .git/hooks 目录下。
commit-msg 脚本可以使用 Shell、Ruby、Python 等语言实现。
  • 案例1
### Squash the commits with the same Change-Id or ensure Change-Ids are unique for each commit
shell
Enumerating objects: 9, done.
Counting objects: 100% (9/9), done.
Delta compression using up to 4 threads
Compressing objects: 100% (5/5), done.
Writing objects: 100% (5/5), 473 bytes | 473.00 KiB/s, done.
Total 5 (delta 4), reused 0 (delta 0)
remote: Resolving deltas: 100% (4/4)
remote: Processing changes: refs: 1, done    
To ssh://sg-8-130.hst.xxxxx.net:29418/xxxx/xxxxxx
 ! [remote rejected]   HEAD -> refs/for/dev (same Change-Id in multiple changes.
Squash the commits with the same Change-Id or ensure Change-Ids are unique for each commit)
error: failed to push some refs to 'ssh://[email protected]:29418/xxxxx/xxxxx'
在dev分支上有重复的change-id,使用
shell
git commit --amend 
  • 案例2 缺失 Change-Id
  1. 如果缺失 Change-Id 的是最后一个 (head) commit, 使用以下命令即可解决问题
  $ git commit --amend
  1. 如果缺失 Change-Id 的不是最后一个 commit,第二个提交缺失 Change-Id, 可用 reset 方法:
  $ git reset 1a9096a34322885ac101175ddcac7dab4c52665d
  $ git commit --amend
  $ git add ......
  $ git commit -m "你的提交日志"
  $ git push review HEAD:refs/for/dev
  1. 使用交互式rebase 找回任意提交位置的 Change-Id 以及有多个 commit 缺失 Change-Id 的情况
// 找到缺失 Change-Id 的那个 commit:
// 执行 git rebase -i, 参数为 该提交的上一个提交的 commit-id (本例中为 "表单" 那个提交):
   $ git rebase -I d714bcde0c14ba4622d28952c4b2a80882b19927
//将缺失了 Change-Id 的 commit 前面的 pick 改为 reword 即可
//逐个编辑 commit-msg 可以不需要修改 保存推出即可
$ git log
commit 8aaaa749db4a5b105aa746659c5cd266ac82fffe
Author: liux 
Date:   Mon Dec 19 17:43:24 2016 +0800
 
    I am commit message 3
     
    Change-Id: Ic89d5ce6ce4de70d1dcb315ce543c86a2b3ac003
 
commit 8e1cad33bcd98e175cba710b1eacfd631a5dda41
Author: liux 
Date:   Mon Dec 19 17:43:00 2016 +0800
 
    I am commit message 2
     
    Change-Id: I9d2af0cc31423cf808cd235de0ad02abf451937d
 
commit 1a9096a34322885ac101175ddcac7dab4c52665d
Author: liux 
Date:   Mon Dec 19 15:23:36 2016 +0800
 
    I am commit message 1
 
commit d714bcde0c14ba4622d28952c4b2a80882b19927
Author: shangsb 
Date:   Wed Dec 14 09:20:52 2016 +0800
 
    这是一个提交
     
    Change-Id: I629b2bedff95491875f63634ad3da199612735b6
$ git rebase -I d714bcde0c14ba4622d28952c4b2a80882b19927
这个命令会打开默认的编辑器,一般为 vi. 内容如下:
pick 1a9096a I am commit message 1
pick 8e1cad3 I am commit message 2
pick 8aaaa74 I am commit message 3
# Rebase d714bcd..8aaaa74 onto d714bcd
#
# Commands:
#  p, pick = use commit
#  r, reword = use commit, but edit the commit message
#  e, edit = use commit, but stop for amending
#  s, squash = use commit, but meld into previous commit
#  f, fixup = like "squash", but discard this commit's log message
#  x, exec = run command (the rest of the line) using shell
#
# 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
reword 1a9096a I am commit message 1
pick 8e1cad3 I am commit message 2
pick 8aaaa74 I am commit message 3
# Rebase d714bcd..8aaaa74 onto d714bcd
#
# Commands:
#  p, pick = use commit
#  r, reword = use commit, but edit the commit message
#  e, edit = use commit, but stop for amending
#  s, squash = use commit, but meld into previous commit
#  f, fixup = like "squash", but discard this commit's log message
#  x, exec = run command (the rest of the line) using shell
#
# 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

疑问

  • A-B-C 应该在最新节点C上追加 假如我想在B或者A上追加应该怎么处理
  • 消息分支已经push 并且已经合并到master-pre 最终合并到master 而我本地追踪的是远程master 但是还是显示超前一个版本
  • 错误操作导致我的分支出现别人的代码节点 并且都处于待push的状态 也就是超前远程仓库n个版本

参考文档:
https://www.jianshu.com/p/4079284dd970
https://www.jianshu.com/p/4a8f4af4e803

你可能感兴趣的:(git入门)