Git Pull:忽略本地更改

GitGitBeginner
立即练习

💡 本教程由 AI 辅助翻译自英文原版。如需查看原文,您可以 切换至英文原版

简介

本教程全面介绍了 git pull --ignore-unmerged 命令,该命令允许你在 Git 仓库中优先使用远程更改而非本地更改。无论你是在团队项目中工作,还是需要快速将本地代码库与远程仓库同步,本教程都将帮助你了解使用此命令的场景、好处以及潜在风险。

在这个实验中,你将学习如何设置 Git 仓库、制造冲突性更改,以及使用 git pull --ignore-unmerged 命令解决冲突。你还将探索在 Git 工作流程中处理冲突的其他方法。

设置 Git 仓库

在探索 Git pull 命令之前,让我们先设置一个简单的 Git 仓库来进行操作。这将为你提供一个实际的环境,以便理解 Git 如何处理更改和冲突。

创建新仓库

首先,让我们为 Git 仓库创建一个新目录。打开终端并执行以下命令:

cd ~/project
mkdir git-pull-demo
cd git-pull-demo

现在,在这个目录中初始化一个 Git 仓库:

git init

你应该会看到类似以下的输出:

Initialized empty Git repository in /home/labex/project/git-pull-demo/.git/

配置 Git 用户信息

为了进行提交,Git 需要知道你的身份。使用以下命令设置你的用户名和电子邮件:

git config --local user.name "Learner"
git config --local user.email "[email protected]"

创建并提交初始文件

让我们创建一些示例文件来进行操作。首先,创建一个简单的文本文件:

echo "## Git Pull Demo" > README.md
echo "This is the first line of the file." > file1.txt

现在将这些文件添加到暂存区并进行首次提交:

git add README.md file1.txt
git commit -m "Initial commit"

输出应该如下所示:

[main (root-commit) xxxxxxx] Initial commit
 2 files changed, 2 insertions(+)
 create mode 100644 README.md
 create mode 100644 file1.txt

恭喜你,你已经成功创建了一个带有初始提交的 Git 仓库。让我们检查一下仓库的状态:

git status

你应该会看到:

On branch main
nothing to commit, working tree clean

这表明你所有的更改都已提交。现在你有了一个可用的 Git 仓库,可以进行下一步操作了。

模拟远程仓库

为了理解 git pull 的工作原理,我们需要模拟一个远程仓库。在实际场景中,这个仓库可能托管在 GitHub、GitLab 或 Bitbucket 等平台上。在这个实验中,我们将创建一个本地目录来充当我们的“远程”仓库。

创建“远程”仓库

让我们创建一个裸仓库(bare repository)来充当我们的远程仓库:

cd ~/project
mkdir remote-repo.git
cd remote-repo.git
git init --bare

你应该会看到:

Initialized empty Git repository in /home/labex/project/remote-repo.git/

裸仓库是一个没有工作目录的 Git 仓库,它被设计为一个中央仓库,你可以向其中推送更改并从中拉取更改。

将本地仓库连接到远程仓库

现在,回到你的本地仓库并添加远程仓库:

cd ~/project/git-pull-demo
git remote add origin ~/project/remote-repo.git

将本地更改推送到远程仓库

将你的本地更改推送到远程仓库:

git push -u origin main

输出应该如下所示:

Enumerating objects: 4, done.
Counting objects: 100% (4/4), done.
Delta compression using up to 2 threads
Compressing objects: 100% (2/2), done.
Writing objects: 100% (4/4), 279 bytes | 279.00 KiB/s, done.
Total 4 (delta 0), reused 0 (delta 0)
To /home/labex/project/remote-repo.git
 * [new branch]      main -> main
Branch 'main' set up to track remote branch 'main' from 'origin'.

这个命令将你的本地 main 分支推送到远程仓库,并使用 -u 标志设置本地分支和远程分支之间的跟踪关系。

验证连接

要验证你的本地仓库是否已正确连接到远程仓库,请运行:

git remote -v

你应该会看到:

origin  /home/labex/project/remote-repo.git (fetch)
origin  /home/labex/project/remote-repo.git (push)

这表明你的本地仓库已连接到名为“origin”的远程仓库。

现在我们已经设置好了本地和远程仓库,接下来可以了解如何处理冲突以及使用 git pull --ignore-unmerged 命令了。

创建冲突更改

在这一步中,我们将创建一个场景,使远程仓库中的更改与你的本地更改产生冲突。这将帮助我们理解 Git 如何处理冲突,以及为什么 git pull --ignore-unmerged 命令可能会有用。

创建新的仓库克隆

首先,让我们创建仓库的第二个克隆,以模拟团队成员进行更改:

cd ~/project
git clone remote-repo.git team-member-repo
cd team-member-repo

你应该会看到:

Cloning into 'team-member-repo'...
done.

在“团队成员”仓库中进行更改

现在,让我们在这个仓库中修改 file1.txt

echo "This line was added by a team member." >> file1.txt
git add file1.txt
git commit -m "Team member added a line"
git push origin main

你应该会看到:

[main xxxxxxx] Team member added a line
 1 file changed, 1 insertion(+)
Enumerating objects: 5, done.
Counting objects: 100% (5/5), done.
Delta compression using up to 2 threads
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 325 bytes | 325.00 KiB/s, done.
Total 3 (delta 0), reused 0 (delta 0)
To /home/labex/project/remote-repo.git
   xxxxxxx..xxxxxxx  main -> main

在原始仓库中进行冲突更改

现在,回到你的原始仓库,并对同一个文件进行不同的更改:

cd ~/project/git-pull-demo
echo "This line was added locally." >> file1.txt
git add file1.txt
git commit -m "Added a line locally"

你应该会看到:

[main xxxxxxx] Added a line locally
 1 file changed, 1 insertion(+)

尝试拉取更改

现在,尝试从远程仓库拉取更改:

git pull origin main

由于你和“团队成员”对同一个文件进行了更改,Git 会报告冲突:

From /home/labex/project/remote-repo
 * branch            main       -> FETCH_HEAD
Auto-merging file1.txt
CONFLICT (content): Merge conflict in file1.txt
Automatic merge failed; fix conflicts and then commit the result.

查看冲突

让我们检查包含冲突的文件:

cat file1.txt

你应该会看到类似以下内容:

This is the first line of the file.
<<<<<<< HEAD
This line was added locally.
=======
This line was added by a team member.
>>>>>>> xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

Git 用 <<<<<<< HEAD=======>>>>>>> 标记了冲突部分。======= 之前的部分是你的本地更改,之后的部分是远程更改。

这是一个典型的合并冲突场景。在下一步中,我们将使用 git pull --ignore-unmerged 选项来解决这个冲突。

使用 git pull 并搭配 --ignore-unmerged 选项

既然我们已经在本地仓库和远程仓库之间制造了冲突,接下来让我们探讨如何使用 git pull --ignore-unmerged 选项来解决这个冲突。

理解 --ignore-unmerged 选项

--ignore-unmerged 选项会告知 Git,当出现冲突时,优先采用远程仓库的更改而非本地仓库的更改。在你明确知道远程仓库的更改比本地更改更重要的情况下,这个选项会很有用。

中止当前合并操作

在使用 --ignore-unmerged 选项之前,我们需要中止当前正在进行的合并操作:

cd ~/project/git-pull-demo
git merge --abort

这个命令会将你的工作目录恢复到合并尝试之前的状态。我们来验证一下文件的内容:

cat file1.txt

现在你应该只能看到你本地的更改:

This is the first line of the file.
This line was added locally.

使用 --ignore-unmerged 选项

现在,让我们使用 git pull --ignore-unmerged 选项:

git pull --ignore-unmerged origin main

你可能会注意到,Git 仍然会报告冲突:

From /home/labex/project/remote-repo
 * branch            main       -> FETCH_HEAD
Auto-merging file1.txt
CONFLICT (content): Merge conflict in file1.txt
Automatic merge failed; fix conflicts and then commit the result.

这是因为 --ignore-unmerged 选项的实际作用与它的名称所暗示的有所不同。它并不会直接通过忽略你的本地更改来解决冲突,而是允许 Git 在存在未合并条目的情况下继续进行合并操作。

理解实际发生的情况

要优先采用远程更改而非本地更改,正确的做法是使用 --strategy-option theirs 选项:

git reset --hard ## 警告:这将丢弃所有未提交的更改
git pull -X theirs origin main

输出应该如下所示:

From /home/labex/project/remote-repo
 * branch            main       -> FETCH_HEAD
Updating xxxxxxx..xxxxxxx
Fast-forward
 file1.txt | 1 +
 1 file changed, 1 insertion(+)

这个命令会让 Git 在解决冲突时,优先选择远程更改(“theirs”)而非本地更改(“ours”)。

现在让我们检查一下文件的内容:

cat file1.txt

你应该会看到:

This is the first line of the file.
This line was added by a team member.

如你所见,远程更改已经优先于你的本地更改被采用。--strategy-option theirs 选项是一种更直接的方法,能实现很多人误以为 --ignore-unmerged 选项所能达成的效果。

何时使用 --ignore-unmerged

实际上,--ignore-unmerged 选项在你希望拉取没有冲突的文件的更新,同时将有冲突的文件留待后续手动解决的情况下更为有用。

为了更清楚地展示这一点,让我们创建另一个场景:

## 本地添加一个新文件
echo "This is a new local file." > local_file.txt
git add local_file.txt
git commit -m "Added local_file.txt"

## 在团队成员的仓库中进行更改
cd ~/project/team-member-repo
echo "This is a second line by team member." >> file1.txt
echo "This is a new remote file." > remote_file.txt
git add file1.txt remote_file.txt
git commit -m "Team member made more changes"
git push origin main

## 回到你的仓库
cd ~/project/git-pull-demo
## 对 file1.txt 进行不同的更改
echo "This is another local change." >> file1.txt
git add file1.txt
git commit -m "Made another local change"

现在,当你尝试拉取更改时,会遇到冲突:

git pull origin main

输出如下:

From /home/labex/project/remote-repo
 * branch            main       -> FETCH_HEAD
Auto-merging file1.txt
CONFLICT (content): Merge conflict in file1.txt
Automatic merge failed; fix conflicts and then commit the result.

让我们中止合并操作,然后尝试使用 --ignore-unmerged 选项:

git merge --abort
git pull --ignore-unmerged origin main

这可能仍然会显示冲突,但它会让你获取所有没有冲突的更改(例如 remote_file.txt),同时将有冲突的文件(file1.txt)留待你手动解决。

处理冲突的其他方法

虽然 git pull --ignore-unmergedgit pull -X theirs 命令在特定场景下很有用,但你还应该了解其他几种处理冲突的方法。这些方法能让你在合并过程中拥有更多控制权,并且在很多情况下更加安全。

1. 手动解决冲突

最常见且最安全的方法是手动解决冲突。让我们创建一个全新的冲突场景并手动解决它:

cd ~/project/git-pull-demo
git reset --hard HEAD~1 ## 回退一个提交

你应该会看到:

HEAD is now at xxxxxxx Added local_file.txt

现在对 file1.txt 进行更改:

echo "This is a different local change." >> file1.txt
git add file1.txt
git commit -m "Made a different local change"

现在从远程仓库拉取更改:

git pull origin main

你会看到冲突信息:

From /home/labex/project/remote-repo
 * branch            main       -> FETCH_HEAD
Auto-merging file1.txt
CONFLICT (content): Merge conflict in file1.txt
Automatic merge failed; fix conflicts and then commit the result.

使用 nano 编辑器编辑文件以解决冲突:

nano file1.txt

nano 编辑器中,你可以看到冲突标记。编辑文件以保留双方的更改,或根据需要进行其他修改。例如,你可能希望文件内容如下:

This is the first line of the file.
This line was added by a team member.
This is a second line by team member.
This is a different local change.

保存文件(按 Ctrl+O,然后按 Enter)并退出 nano(按 Ctrl+X)。

现在完成合并过程:

git add file1.txt
git commit -m "Manually resolved conflict"

你应该会看到:

[main xxxxxxx] Manually resolved conflict

2. 使用 git stash

另一种方法是使用 git stash 临时保存你的本地更改,拉取远程更改,然后重新应用你的更改:

## 对 file1.txt 进行新的更改
echo "This is yet another local change." >> file1.txt

## 使用 git stash 保存本地更改
git stash

## 拉取远程更改
git pull origin main

## 重新应用本地更改
git stash pop

如果在运行 git stash pop 时出现冲突,Git 会提示你,你可以手动解决这些冲突。

3. 创建特性分支

第三种方法是为你的本地更改创建一个特性分支:

## 创建并切换到新分支
git checkout -b feature-branch

## 进行更改
echo "This is a change in the feature branch." >> file1.txt
git add file1.txt
git commit -m "Made a change in feature branch"

## 切换回主分支
git checkout main

## 拉取远程更改
git pull origin main

## 合并特性分支
git merge feature-branch

如果在合并过程中出现冲突,Git 会让你在完成合并之前手动解决这些冲突。

4. 使用合并工具

Git 还支持各种合并工具,这些工具可以让冲突解决过程更加直观和可视化。你可以使用以下命令配置 Git 使用你喜欢的合并工具:

git config --global merge.tool <tool-name>

当你遇到冲突时,可以运行:

git mergetool

这将打开你配置的合并工具,帮助你解决冲突。

这些方法各有优缺点和适用场景。最佳方法取决于你的具体情况和个人偏好。

总结

在本次实验中,你学习了 Git 的冲突解决机制,特别探索了 git pull --ignore-unmerged 命令。你获得了以下方面的实践经验:

  1. 设置 Git 仓库并将其连接到远程仓库
  2. 创建并模拟本地仓库和远程仓库之间的冲突更改
  3. 理解 git pull --ignore-unmerged 命令的作用及其局限性
  4. 使用更有效的 git pull -X theirs 命令来优先采用远程更改
  5. 探索处理冲突的其他方法,包括:
    • 手动解决冲突
    • 使用 git stash
    • 创建特性分支
    • 利用合并工具

关键要点在于,虽然像 git pull --ignore-unmergedgit pull -X theirs 这样的命令在特定场景下很有用,但使用时应谨慎。在大多数情况下,手动解决冲突能让你拥有更多控制权,并有助于确保重要更改不会意外丢失。

通过理解这些 Git 概念和命令,你现在能更好地处理协作开发环境中的代码冲突,使你的 Git 工作流程更高效,且更不容易出错。