梳理一下标准流程:


一、正常的工作流程(避免冲突)

1. 初次获取仓库(只需一次)

git clone <仓库地址>
cd <仓库目录>

之后就不需要再 clone 了,直接进入已有的本地仓库目录工作。

2. 每次开始工作前,先同步远程最新代码

git pull --rebase origin master

或者普通的合并方式:

git pull origin master

推荐使用 --rebase 保持线性历史,减少不必要的合并提交。

如果远程没有更新,git pull 会直接告诉你已经是最新的。

3. 修改文件,然后提交

git add .
git commit -m "描述你的修改"

4. 推送前(可选)检查状态

git log --oneline --graph --decorate --all -20

或者更简单地:

git status

确认本地和远程是否分叉。如果 git pull 之后没有再出现新的远程提交,通常不会分叉。

5. 推送到远程

git push -u origin master
  • -u 参数只在第一次推送时需要,用来设置上游分支,之后可以直接 git push
  • 如果远程没有新提交,你的推送一定是快进(fast-forward),不会报错。

二、如果推送时遇到“non-fast-forward”错误

这说明远程有本地没有的提交,也就是远程在你上次拉取后又有了新提交(别人推的,或者你在 GitHub 网页上操作产生的)。此时需要先整合远程的提交。

解决方法(推荐 rebase)

  1. 拉取远程提交并变基

    git pull --rebase origin master
    
    • 这个命令会自动把远程的提交拉下来,然后把你的本地提交“嫁接”到远程最新提交之后。
    • 如果没有冲突,命令会顺利结束,此时你的本地历史已经包含了远程提交,且你的提交在最新位置。
    • 注意:如果 git pull --rebase 已经成功完成,就不需要再执行 git rebase --continue
  2. 如果出现冲突,Git 会暂停并提示冲突文件。你需要:

    • 手动编辑冲突文件,删除冲突标记(<<<<<<<=======>>>>>>>),保留正确内容。
    • 执行 git add <冲突文件>git add . 标记为已解决。
    • 继续变基:
      git rebase --continue
      
    • 重复直到变基完成(提示 “Successfully rebased and updated refs/heads/master.”)。
  3. 推送

    git push origin master
    

    此时因为本地已经包含了远程的所有提交,是快进推送,不会报错。


三、澄清你的表述

你说:“如果遇到有其他人基于某分支的提交,导致我们拉取的版本在提交时会弹出冲突,即两个提交都基于同一分支提交,就先变基git pull –rebase origin master,然后git rebase –continue,最后git push -u origin master?”

这里有一个小误区:

  • git pull --rebase origin master 本身就会执行变基操作。如果变基过程中出现冲突,它不会自动完成,而是停下来让你解决冲突。解决冲突后你需要执行 git rebase --continue 来继续变基。
  • 所以顺序是:
    1. git pull --rebase origin master (可能因冲突而暂停)
    2. 解决冲突 → git add .
    3. git rebase --continue
    4. git push origin master (不需要再加 -u,除非是第一次推送该分支)

如果 git pull --rebase 没有冲突,它就直接完成了,不需要 git rebase --continue


四、总结推荐的标准工作流

# 1. 进入仓库目录(不是每次clone)
cd your-repo

# 2. 同步远程最新代码
git pull --rebase origin master

# 3. 修改文件...

# 4. 提交
git add .
git commit -m "你的提交信息"

# 5. 推送
git push origin master   # 第一次可用 git push -u origin master

如果推送时发现被拒绝(因为远程有新提交),回到第2步执行 git pull --rebase 再推送。

这样就能避免绝大多数“非快进”错误,也能保持提交历史整洁。

五、强制推送回退

git commit –amend:只适用于 “刚写完代码,还没 push” 的情况。作用是 “替换” 上一次提交。
它不是用来提交的。如果你add一次新的改动,然后输入这个命令,会看到的上一次commit信息,如果你修修改改提交了,会出现阻止信息。
如果应对这次阻止你直接输入了——

git push --force-with-lease origin master

强制推送以恢复远程,会覆盖掉上一次提交信息。
遇到这个情况你需要在本地输入命令以查看操作日志,找到被 amend 之前的那个提交哈希值(比如叫 a1b2c3d)

# 1. 查看操作日志,找到被 amend 之前的那个提交哈希值(比如叫 a1b2c3d)
git reflog

## 这条命令对比旧提交(708cd3f)和新提交(0f50a4c),把差异存成补丁
git diff 708cd3f 0f50a4c > my_changes.patch

# 2. 把本地分支强行指回那个哈希值(恢复第4次)
git reset --hard a1b2c3d

# 3. 把被覆盖掉的提交重新推回远程,恢复远程的历史
git push --force-with-lease origin master

# 4.把你刚才备份的补丁,应用到当前代码上
git apply my_changes.patch

(如果这一步提示冲突,别怕,那是因为补丁里的内容和你现在的代码略有偏差,手动把补丁里的修改重新加进去就行,通常不会)
我的建议是最好清除当前本地文件夹除了.git外的其他所有文件,把本地的备份拿过来放进去。

# 5. 正常提交成为第5次
git add .
git commit -m "这是新增的第5次提交"
git push origin master

六、提交

通常我们见到的git commit -m是跳过编辑器,直接把这句引号里的内容作为提交信息。
如果我们想编辑提交内容应该git commit,它会弹出一个文本编辑器(黑框里的 Vim 或 Nano),让你在里面写长篇大论的提交说明。
此时编辑器会出现一堆以#号开头的文字,这些都是注释说明不会出现在提交信息里。我们输入命令后会默认进入INSERT插入模式,光标来到第一行这个空行。你将提交信息粘贴进编辑器即可。
若想清空编辑器信息,Windows系统可以按Esc键,输入vim快速删除全部内容的命令ggdG然后回车,在输入i回到插入模式。
输入完成后按Esc键,输入!wq回车,提交就完成了。