zoukankan      html  css  js  c++  java
  • 一些常用的 Git 进阶知识与技巧

    1. 同一电脑存在多个 Git 账号

    假设我们在同一电脑上拥有多个 Git 账号,例如公司内部使用的是 Gitlab,个人使用的是 Github 或者 Gitee。那就会遇到一种情况,上班时想给个人开源项目提交代码,但是 Git 绑定的是公司的账号。

    在这种情况下,我们可以让 Git 绑定多个不同的 ssh key,每个 ssh key 对应一个不同的 Git 服务器。

    生成第一个 ssh key:

    ssh-keygen -t rsa -C "xxx@xxx.xx"
    

    生成第二个 ssh key:

    ssh-keygen -t rsa -f path/to/file  -C "xxx@xxx.xx"
    

    参数 -f 表示指定生成的文件名, path/to/file 是文件名路径,例如 ~/.ssh/id_rsa_github

    执行上面两条命令后会得到两对 ssh key。

    image.png

    这时还需要在该目录下创建一个 config 文件。写上以下内容:

    Host github.com
    HostName github.com
    User git
    IdentityFile ~/.ssh/id_rsa_github # 私钥文件路径
                                                                
    Host gitlab.com
    HostName gitlab.com
    User git
    IdentityFile ~/.ssh/id_rsa
    
    Host gitee.com
    HostName gitee.com
    User git
    IdentityFile ~/.ssh/id_rsa_github
    

    这个配置文件的作用是指定私钥文件位置。

    然后我们可以把第一个密钥配置到公司的 Gitlab 服务器,并把相应的 Git 账号和邮箱设成全局。

    git config --global user.name "xxx"
    git config --global user.email "xxx@xxx.xx"
    

    然后把另一对 ssh key 配置到 Github 上,并在电脑上的 Github 项目里单独配置 Git 用户姓名和邮箱。

    git config user.name "xxx"
    git config user.email "xxx@xxx.xx"
    

    至此,我们就大功告成了。可以同时在不同的 Gitlab 和 Github 项目上提交代码了。

    2. 修改 git commit 记录的用户姓名和邮箱

    假设电脑上同时存在 Gitlab 和 Github 项目,其中 Gitlab 用户信息已经全局配置过了。现在新拉了一个 Github 项目,提交了一个 commit 并且已经推送到了远程仓库。这时发现该项目未配置 Github 的用户信息,默认使用的是全局账号 Gitlab 的用户信息。

    我们可以通过以下命令来修改最近一次提交的用户信息:

    git commit --amend --author="username <yyy@ccc.com>" --no-edit
    

    username 是用户名,用户邮箱旁边的 <> 符号不能去掉。修改后再执行 git push -f 推送到远程仓库。

    如果要修改多个 commit 的用户信息怎么办? 可以通过以下的代码来修改:

    git filter-branch --commit-filter '
        if [ "$GIT_AUTHOR_EMAIL" = "tanguangzhi@shiqiao.com" ];
        then
                GIT_AUTHOR_NAME="woai3c";
                GIT_AUTHOR_EMAIL="411020382@qq.com";
                git commit-tree "$@";
        else
                git commit-tree "$@";
        fi' HEAD
    

    将上述代码中的用户名和邮箱修改后,保存为 .sh 格式的文件,例如 edit.sh。然后在项目根目录下执行 sh edit.sh(windows 下可右击-> Git Bash Here -> sh edit.sh),再执行 git push -f 强推即可。

    3. 修改某个历史记录的消息

    假设当前分支有 a b c d 四个 commit 记录:

    a
    b
    c
    d
    

    如果你想对 c 记录的消息进行修改。可以使用 git rebasec 记录换到最前面,然后使用 git commit --amend 对其消息进行修改。

    具体操作步骤

    执行以下命令对记录 d 前面的三个 commit 进行编辑:

    git rebase -i d
    

    进行 vim 编辑界面后,移动光标到 c 记录上,按下 dd 剪切该记录,然后移动光标到第一行,按下 p 粘贴,再输入 :wq 保存。

    执行 git commit --amend 对切换顺序后的 c 记录进行修改。进入 vim 编辑界面后,按 i 进行修改,然后按 ESC,再输入 :wq 保存。

    最后用前面讲过的 git rebase 操作将 c 记录恢复到原来的位置。

    image

    这个过程的执行结果就和上图一样,这是当前分支修改后和远程分支上的对比,箭头指向的记录消息就是修改后的消息。

    如果想把修改后的记录同步到远程仓库,这时只要执行 git push -f 就可以了。

    第二种方式

    1. 使用 git checkout -b <branchName> c 从指定记录切出一个分支
    2. 在新分支使用 git commit --amend 修改提交消息
    3. 使用 git cherry-pickb a 记录,追加到新分支(注意,这里的 b a 提交记录是指原分支上的 commit,也就是选取原分支上的 b a 记录添加到新分支上,这样新分支上的记录就变成了 a b c,并且 c 记录的提交消息在第二步已经修改过)
    4. 使用 git checout 原分支名 切换回原来的分支,再执行 git rebase <branchName> 合并新分支,最后强推到远程分支

    4. 挑选指定的 commit 进行合并

    假设你切了一个 bugFix 分支来修复线上 bug,经过一段时间的努力后终于将 bug 修复了。但是为了调试(加了很多 debug 代码)或其他原因,bugFix 上多了很多无用的记录消息。

    commit3: 修复登录 bug
    commit2: 添加 debug 语句
    commit1: 添加 console 语句
    

    例如上面的三个记录,前面的两个记录添加了很多调试代码,在最后一个记录终于修复了 bug,并且删除了调试代码。这时如果直接将 bugFix 分支合到 master 分支,就会把调试的记录也合并进来。

    这时可以使用 git cherry-pick 只将最后一个记录合并到 master 分支。或者使用 git rebase 将 bugFix 分支另外两个记录抛弃,然后再合并。

    5. ^~ 的区别

    操作符 ^~ 符一样,后面也可以跟一个数字。 ~ 表示向上返回几代记录。

    但是该操作符后面的数字与 ~ 后面的不同,并不是用来指定向上返回几代,而是指定合并提交记录的第几个父记录。

    Git 默认选择合并提交的“第一个”父记录,在操作符 ^ 后跟一个数字可以改变这一默认行为。

    单看文字可能不太好理解,下面看几个示例。

    image.png

    执行命令 git checkout main^ 回到第一个父记录(原来 HEAD 指向 c3,现在指向 c1)。

    image.png

    执行命令 git checkout main^2 回到第二个父记录(原来 HEAD 指向 c3,现在指向 c2)。

    最后再来一个更复杂的示例:

    G   H   I   J
     \ /     \ /
      D   E   F
       \  |  / \
        \ | /   |
         |/    |
          B     C
           \   /
            \ /
             A
    A =      = A^0
    B = A^   = A^1     = A~1
    C = A^2  = A^2
    D = A^^  = A^1^1   = A~2
    E = B^2  = A^^2
    F = B^3  = A^^3
    G = A^^^ = A^1^1^1 = A~3
    H = D^2  = B^^2    = A^^^2  = A~2^2
    I = F^   = B^3^    = A^^3^
    J = F^2  = B^3^2   = A^^3^2
    

    通过这些示例我们还能发现 ~n 等于连续的 n 个 ^

    6. git revertgit reset 的区别

    git reset 可以回退 Git 的历史记录。例如当前分支有三个记录,并且 HEAD 指向 c 记录:

    c <- HEAD
    b 
    a
    

    如果我们想回退到 b 记录,只要执行 git reset b 就可以了:

    b <- HEAD 
    a
    

    接着使用 git push -f 将回退版本后的分支强制推送到远程仓库,这样本地分支和远程分支就同步了。

    git push -f
    

    git revert 也可以撤销记录,只不过它撤销的记录不会消失,这一点和 git reset 不一样。git reset 撤销的记录就跟消失了一样。

    现在我们用 git revert 来重新演示下刚才的操作:

    c
    b 
    a
    

    如果我们执行 git revert b,则会在当前分支上再生成一个新的 commit 记录,变成 a b c b',这个 b' 的状态和记录 b 是一样的。

    也就是说,执行 git reset b 后,当前的分支记录会变成 a b。执行 git revert b 后,当前的分支记录会变成 a b c b'

    如果你想让别人知道你撤销过记录,就使用 git revert,因为它会留下撤销的记录,否则用 git reset

    参考资料

  • 相关阅读:
    mysql5.5 uuid做主键与int做主键的性能实测
    dom4j解析xml字符串实例
    spring自动注入是单例还是多例?单例如何注入多例?
    Spring中Bean的五个作用域
    【总结】瞬时高并发(秒杀/活动)Redis方案
    浅谈分布式事务
    基于Redis实现分布式锁
    MySQL事务隔离级别详解
    Redis学习手册(Sorted-Sets数据类型)
    Redis的快照持久化-RDB与AOF
  • 原文地址:https://www.cnblogs.com/woai3c/p/15527563.html
Copyright © 2011-2022 走看看