介绍
Git 是一个强大的版本控制系统,可以帮助开发者管理他们的代码并有效地协作。然而,你有时可能会遇到令人困惑的错误消息,尤其是在你刚开始使用 Git 的时候。一个常见的错误是“Your local changes would be overwritten by merge”。当 Git 无法安全地合并更改,因为它会覆盖你未提交的本地修改时,就会发生此错误。
在这个实验(Lab)中,你将学习导致此错误的原因、如何解决它,以及如何在未来的 Git 工作流程中实施防止此错误发生的策略。
💡 本教程由 AI 辅助翻译自英文原版。如需查看原文,您可以 切换至英文原版
Git 是一个强大的版本控制系统,可以帮助开发者管理他们的代码并有效地协作。然而,你有时可能会遇到令人困惑的错误消息,尤其是在你刚开始使用 Git 的时候。一个常见的错误是“Your local changes would be overwritten by merge”。当 Git 无法安全地合并更改,因为它会覆盖你未提交的本地修改时,就会发生此错误。
在这个实验(Lab)中,你将学习导致此错误的原因、如何解决它,以及如何在未来的 Git 工作流程中实施防止此错误发生的策略。
在深入研究解决合并冲突之前,让我们先了解基本的 Git 工作流程,并设置我们的环境来演示这个错误。
Git 是一个分布式版本控制系统,允许多个开发者在同一个代码库上工作,而不会相互干扰。它会跟踪文件随时间的变化,允许你在需要时恢复到之前的版本。
一个典型的 Git 工作流程包括以下步骤:
git add
暂存更改git commit
提交更改git push
将更改推送到远程仓库git pull
从远程仓库拉取更改首先,导航到我们的项目目录:
cd /home/labex/project/git-merge-demo
让我们检查一下我们仓库的状态:
git status
你应该看到类似这样的输出:
On branch main
nothing to commit, working tree clean
现在,让我们检查一下我们有哪些分支:
git branch
你应该看到:
development
* main
星号 (*) 表示你当前在 main
分支上。让我们检查一下我们仓库中的文件:
ls -la
你应该看到:
total 20
drwxr-xr-x 3 labex labex 4096 ... .
drwxr-xr-x 3 labex labex 4096 ... ..
drwxr-xr-x 8 labex labex 4096 ... .git
-rw-r--r-- 1 labex labex 24 ... README.md
-rw-r--r-- 1 labex labex 27 ... script.js
-rw-r--r-- 1 labex labex 25 ... styles.css
让我们看看这些文件的内容:
cat README.md
cat script.js
cat styles.css
太棒了!现在你了解了我们仓库的结构。在下一步中,我们将创建一个生成“local changes would be overwritten by merge”错误的场景。
在这一步中,我们将创建一个导致“Your local changes would be overwritten by merge”错误的场景。这将帮助你理解为什么会发生这个错误。
首先,让我们切换到 development
分支并进行一些更改:
git checkout development
你应该看到:
Switched to branch 'development'
现在,让我们修改 script.js
文件:
echo "console.log('Hello from development branch!');" > script.js
让我们提交这个更改:
git add script.js
git commit -m "Update script.js on development branch"
你应该看到:
[development xxxxxxx] Update script.js on development branch
1 file changed, 1 insertion(+), 1 deletion(-)
现在,让我们切换回 main
分支:
git checkout main
让我们验证一下我们是否在 main 分支上:
git branch
你应该看到:
development
* main
现在,让我们在 main
分支上修改同一个文件 (script.js
),但这次我们不会提交更改:
echo "console.log('Hello from main branch!');" > script.js
现在我们在工作目录中有未提交的更改,让我们尝试将 development
分支合并到 main
分支中:
git merge development
你应该看到一条类似这样的错误消息:
error: Your local changes to the following files would be overwritten by merge:
script.js
Please commit your changes or stash them before you merge.
Aborting
恭喜你!你已经成功创建了一个生成“Your local changes would be overwritten by merge”错误的场景。
发生此错误的原因是:
development
分支上修改了 script.js
并提交了更改。main
分支上修改了 script.js
,但没有提交更改。在下一步中,我们将学习如何解决此错误。
解决“Your local changes would be overwritten by merge”错误的最常见和最有用的方法之一是使用 git stash
。git stash
命令会暂时保存你未提交的更改,以便你稍后应用它们。
git stash
是一个 Git 命令,它会获取你未提交的更改(包括已暂存和未暂存的),将它们保存起来以备后用,然后还原你工作副本中的更改。
让我们使用 git stash
来保存我们未提交的更改:
git stash
你应该看到类似这样的输出:
Saved working directory and index state WIP on main: xxxxxxx Initial commit
此消息确认你的更改已保存。让我们验证一下我们的工作目录现在是否干净:
git status
你应该看到:
On branch main
nothing to commit, working tree clean
现在让我们检查 script.js
的内容:
cat script.js
你应该看到原始内容:
console.log('Hello, Git!');
现在我们的工作目录是干净的,我们可以安全地合并 development
分支:
git merge development
你应该看到:
Updating xxxxxxx..xxxxxxx
Fast-forward
script.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
让我们再次检查 script.js
的内容:
cat script.js
现在你应该看到:
console.log('Hello from development branch!');
现在我们已经成功地合并了 development
分支,让我们检索我们暂存的更改:
git stash list
你应该看到:
stash@{0}: WIP on main: xxxxxxx Initial commit
这表明我们有一个已保存的 stash。让我们应用它:
git stash apply
你可能会看到一条冲突消息:
Auto-merging script.js
CONFLICT (content): Merge conflict in script.js
这是正常的,因为 Git 正在尝试将你暂存的更改应用到已合并的文件之上。让我们检查 script.js
的内容:
cat script.js
你应该看到类似这样的内容:
<<<<<<< Updated upstream
console.log('Hello from development branch!');
=======
console.log('Hello from main branch!');
>>>>>>> Stashed changes
这是一个合并冲突,你需要手动解决。使用 nano 打开文件:
nano script.js
编辑文件以保留两个更改或选择一个:
// Keep both changes
console.log("Hello from development branch!");
console.log("Hello from main branch!");
通过按 Ctrl+O
,然后 Enter
来保存文件,并通过按 Ctrl+X
退出 nano。
现在,让我们暂存并提交已解决的冲突:
git add script.js
git commit -m "Merge development branch and resolve conflict"
恭喜你!你已经成功地使用 git stash
解决了“Your local changes would be overwritten by merge”错误。
在之前的步骤中,我们使用了 git stash
来解决“Your local changes would be overwritten by merge”错误。在这一步中,我们将探讨处理这种情况的替代方法。
避免“Your local changes would be overwritten by merge”错误的最简单方法之一是在执行合并操作之前提交你的更改。
让我们创建另一个场景来演示这一点。首先,让我们修改 styles.css
文件:
echo "body { background-color: #f0f0f0; }" > styles.css
现在,与其暂存我们的更改,不如提交它们:
git add styles.css
git commit -m "Update styles.css on main branch"
你应该看到:
[main xxxxxxx] Update styles.css on main branch
1 file changed, 1 insertion(+), 1 deletion(-)
现在,让我们切换到 development
分支,对同一个文件进行更改,并提交它:
git checkout development
echo "body { background-color: #e0e0e0; }" > styles.css
git add styles.css
git commit -m "Update styles.css on development branch"
现在,让我们切换回 main
分支:
git checkout main
如果我们现在尝试合并,就不会有“local changes would be overwritten”错误,因为我们已经提交了我们的更改。但是,我们可能会遇到合并冲突:
git merge development
你可能会看到:
Auto-merging styles.css
CONFLICT (content): Merge conflict in styles.css
Automatic merge failed; fix conflicts and then commit the result.
这是一种不同的冲突,当两个分支都提交了对文件相同部分的更改时,就会发生这种冲突。让我们解决这个冲突:
cat styles.css
你应该看到:
<<<<<<< HEAD
body { background-color: #f0f0f0; }
=======
body { background-color: #e0e0e0; }
>>>>>>> development
让我们编辑文件以解决冲突:
nano styles.css
将内容更改为:
body {
background-color: #f5f5f5;
}
保存文件并提交已解决的冲突:
git add styles.css
git commit -m "Resolve merge conflict in styles.css"
另一种方法是,如果你不再需要你的本地更改,就简单地丢弃它们:
## Create a change to README.md
echo "## Updated README" > README.md
## Check the status
git status
你应该看到:
On branch main
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git checkout -- <file>..." to discard changes in working directory)
modified: README.md
no changes added to commit (use "git add" and/or "git commit -a")
如果你决定不需要这些更改,你可以丢弃它们:
git checkout -- README.md
让我们再次检查状态:
git status
你应该看到:
On branch main
nothing to commit, working tree clean
并且 README.md 的内容已恢复到其原始状态:
cat README.md
这些替代方法为你提供了不同的选项,可以根据你的特定情况和需求来处理“Your local changes would be overwritten by merge”错误。
现在你已经知道如何解决“Your local changes would be overwritten by merge”错误,让我们讨论一些最佳实践,以防止从一开始就发生这个问题。
进行小的、频繁的提交有助于减少合并冲突的几率:
## Make a small change
echo "// Add a comment" >> script.js
## Commit the change
git add script.js
git commit -m "Add a comment to script.js"
在推送你的更改之前,始终从远程仓库拉取更改:
## 在真实场景中,你会这样做:
## git pull origin main
## 由于我们正在本地工作,让我们通过检出 development 并返回来模拟这一点
git checkout development
git checkout main
为每个特性或错误修复创建一个新分支:
## 创建一个新的特性分支
git checkout -b feature-navbar
## Make some changes
echo "/* Navigation bar styles */" >> styles.css
## Commit the changes
git add styles.css
git commit -m "Add navigation bar styles"
让我们回到 main 分支:
git checkout main
保持你的特性分支与主分支同步:
## 切换到特性分支
git checkout feature-navbar
## 在真实场景中,你将与 main 合并或变基:
## git merge main
## or
## git rebase main
## 对于我们的演示,让我们模拟这一点
echo "/* More styles */" >> styles.css
git add styles.css
git commit -m "Add more styles"
## Go back to main
git checkout main
在执行合并或拉取等操作之前,始终检查你的仓库的状态:
git status
你应该看到:
On branch main
nothing to commit, working tree clean
虽然我们无法在实验中演示这一点,但沟通是避免冲突的关键。确保你的团队知道你正在处理哪些文件,以避免同时更改相同的文件。
对于复杂的合并冲突,请考虑使用 GUI 工具:
## 列出可用的 GUI 合并工具(在真实环境中)
## git mergetool --tool-help
## 在我们的例子中,我们只显示通常可用的合并工具
echo "Common merge tools: meld, kdiff3, vimdiff, vscode"
通过遵循这些最佳实践,你可以显著减少合并冲突和“Your local changes would be overwritten by merge”错误在你的 Git 工作流程中发生的频率。
在这个实验中,你学习了如何在 Git 中解决“Your local changes would be overwritten by merge”错误。这是一个常见的问题,当你尝试合并或拉取更改,同时在你的工作目录中有未提交的修改时,就会发生此问题。
本实验涵盖的关键点:
你创建了一个场景,通过在不同的分支中对同一个文件进行更改,触发了“Your local changes would be overwritten by merge”错误。
你学习了多种解决此错误的方法:
git stash
临时保存你的更改git checkout
丢弃不需要的本地更改你探索了防止合并冲突的最佳实践:
git status
通过理解这些概念和技术,你可以更有效地管理你的 Git 工作流程,并避免导致合并冲突的常见陷阱。
请记住,Git 是一个用于版本控制和协作的强大工具,但它需要仔细管理更改以避免冲突。你在本实验中学习的技能将帮助你在与他人有效协作的同时,维护你的代码库的完整性。