假如我在面试中问到git,你又该怎么应对?

本文从实践作业经验动身,叙述了作业种常见的、和git提交代码相关的场景问题,并从此场景中引申出的4点问题,并记载了这些问题的解决办法。

实践场景

我要开发两个功用A和B,公司目前实行的标准是:

  • 首先切换至main分支(也便是项目的主分支),运用git pull拉最新代码,然后运用git checkout -b feat/A切到开发分支,在feat/A上完结功用A的开发之后,commit然后push到长途库房中;
  • 然后开端开发B功用,运用git pull拉最新代码,然后运用git checkout -b feat/B切到开发分支,在feat/B上完结功用B的开发之后,commit然后push到长途库房中。

问题一

在feat/A上提交并推送至长途库房之后,开端开发B功用,可是这个时分因为大意,导致没有做切换到main,然后pull,然后checkout -b feat/B,所以此刻我仍然在feat/A上。开发完B功用之后,不小心commit了,可是没有push到长途库房,请问此刻我该怎么做才干补偿过错,使提交契合标准?

我期望的答案

假如新的commit还没有被推送,处理的代价是最小的,按如下的步骤即可解决:

  1. 运用reset将提交内容返回到作业区
  2. stash feat B的内容
  3. 切换至主分支并拉新代码
  4. 创立B分支
  5. 将修正内容放到B分支上
  6. 提交并推送
# 运用reset将提交内容返回到作业区
git reset HEAD~
# stash feat B的内容
git stash
# 切换至主分支并拉新代码
git checkout main && git pull
# 创立B分支
git checkout -b feat/B
# 将修正内容放到B分支上
git stash pop
# 提交并推送
git add .
git commit -m "feat: B"
git push origin HEAD

问题二

在feat/A上提交并推送至长途库房之后,开端开发B功用,可是这个时分因为大意,导致没有做切换到main,然后pull,然后checkout -b feat/B,所以此刻我仍然在feat/A上。开发完B功用之后,不小心commit了,并且push到了长途库房,请问此刻我该怎么做才干补偿过错,使提交契合标准?

我期望的答案

假如新的commit已经被推送,处理起来是比较棘手的,可是又可以分红两种状况:
假定过错commit的hash值为:abc123

  • feat/A没有被兼并到主分支
    1. 在feat/A上生成一次revert提交记载,掩盖B功用代码
    2. 将revert之后的本地分支推送到长途库房
    3. 切换至主分支并拉新代码
    4. 创立B分支
    5. 运用cherry-pick将abc123提交记载仿制一份到B分支上
    6. 提交并推送
# 在feat/A上生成一次revert提交记载,掩盖B功用代码
git revert abc123
# 将revert之后的本地分支推送到长途库房
git push origin HEAD -f
# 切换至主分支并拉新代码
git checkout main && git pull
# 创立B分支
git checkout -b feat/B
# 运用cherry-pick将abc123提交记载仿制一份到B分支上
git cherry-pick abc123
# 提交并推送
git add .
git commit -m "feat: B"
git push origin HEAD
  • feat/A已经被兼并到主分支
    1. 回到主分支,拉取最新代码,创立然后切换到一个名为fix/revert-A的分支
    2. 在fix/revert-A分支上运用revert abc123掩盖B功用代码
    3. 将fix/revert-A分支推送到长途库房并联络组长兼并到主分支
    4. 切换至主分支并拉新代码
    5. 创立B分支
    6. 运用cherry-pick将abc123提交记载仿制一份到B分支上
    7. 提交并推送
# 回到主分支,拉取最新代码,创立然后切换到一个名为fix/revert-A的分支
git checkout main && git pull && git checkout -b fix/revert-A
# 在fix/revert-A分支上运用revert abc123掩盖B功用代码
git revert abc123
# 将fix/revert-A分支推送到长途库房并联络组长兼并到主分支
git add . && git commit -m "fix: revert" && git push origin HEAD
# 切换至主分支并拉新代码
git checkout main && git pull
# 创立B分支
git checkout -b feat/B
# 运用cherry-pick将abc123提交记载仿制一份到B分支上
git cherry-pick abc123
# 提交并推送
git add .
git commit -m "feat: B"
git push origin HEAD

问题三

运用revert之后,导致feat/A中commit记载多了一次revert记载,我不想要这个revert记载,怎么使其消失?

我期望的答案

这归于问题二的第一种状况,只需在履行“之前rebase一下,将revert记载抹平即可:
假定在feat/A上正常提交A功用发生的commit的记载的hash值为:xyz456

# 在feat/A上生成一次revert提交记载,掩盖B功用代码
git revert abc123
# 运用rebase抹平此次revert记载
git log # 找到xyz456
git rebase -i xyz456^ # 表明将xyz456这个commit之后的提交组成一个
# 根据自己的需要填表,保存,封闭;其实便是把自己不想要的commit前面的pick改成fixup
# 将revert之后的本地分支推送到长途库房
git push origin HEAD -f
# 切换至主分支并拉新代码
git checkout main && git pull
# 创立B分支
git checkout -b feat/B
# 运用cherry-pick将abc123提交记载仿制一份到B分支上
git cherry-pick abc123
# 提交并推送
git add .
git commit -m "feat: B"
git push origin HEAD

问题四

方才提到了rebase,请问rebase和merge的差异是什么,运用机遇有什么不同?

我期望的答案

  • 运用merge兼并代码,会保存开发分支上的提交记载,这有利于之后定位问题和改bug;
  • 运用rebase不是commit记载的引证,而是对改动的仿制,这样的方法不会保存分支上的提交记载;
  • 运用merge的缺点是会发生非常多的无用的提交日志;而运用rebase则恰好相反,没有足够多的提交信息;
  • 正如上面三个问题所述,在开发分支上运用rebase兼并了自己不想要别人看到的revert提交记载,而兼并到主分支main上的时分,总是以merge的方法;
  • 所以rebase主要用在私有分支内部,而merge主要用在私有分支向主分支兼并的时分;
  • 总之,不论是运用merge还是rebase,中心根据是为了便利其他开发者,当然这也是为了便利自己。

最终

这便是我平时作业中遇到的问题,以及我期望我的同事在遇到这些问题之后的处理方法,并且我会把这个当成面试题堆集下来,那么您有没有更好的做法呢?欢迎留言和吐槽~