本地非 Git 项目与远程 GitHub 仓库同步

C. Qiu 于 2024-05-14 发布

记录一次比较神奇的操作。

之前我从 Github 直接下载了某项目源码的 ZIP 压缩包,在本地解压修改使用,对其中的文件既有删改也有新增。最近发现原始仓库大更新,我想把更新合并到本地,然而本地文件夹不是一个 Git 仓库,无法用git pull直接拉取最新代码。

因此,需要将它与远程仓库关联并优雅地合并更新,同时解决合并过程中可能遇到的冲突。

首先备份文件

在进行 Git 操作之前,先备份好当前文件夹,防止误操作导致文件混乱。

操作步骤

假设本地项目文件夹路径为D:\MyProject,远程GitHub仓库地址为https://github.com/username/repository.git

1. 初始化本地Git仓库

在本地先建个 Git 仓库,把现有的所有文件提交到本地仓库里。

打开 Git Bash,或者 CMD/PowerShell:

# 进入你的项目文件夹
cd D:\MyProject

# 初始化Git仓库
git init

2. 提交本地所有改动

将当前所有文件作为一次本地提交。

# 将所有更改添加到暂存区
git add .

# 提交更改
git commit -m "Initial local changes before syncing"

3. 添加远程仓库地址

告诉本地Git仓库远程仓库的位置。

git remote add origin https://github.com/username/repository.git

4. 获取远程仓库信息

下载远程仓库的所有分支和提交历史,但暂时不修改本地工作区。

git fetch origin

5. 合并远程更新到本地分支 (处理不相关历史)

由于本地仓库是全新初始化的,其历史与远程仓库的历史没有共同来源。直接合并会报错 fatal: refusing to merge unrelated histories。此时需要允许合并这些不相关的历史。

git merge origin/main --allow-unrelated-histories

6. 解决合并冲突

执行合并后出现冲突(CONFLICT),因为本地修改和远程更新动了同一文件的同一部分。git status 会显示所有的 “Unmerged paths”。

对于本地项目,我本次的策略是:

6.1 使用远程版本覆盖所有冲突文件

在项目根目录下执行:

# 对于所有冲突文件,采用 "theirs" (即远程 origin/main) 的版本
git checkout --theirs .

6.2 将解决后的文件和新增文件添加到暂存区

上一步用远程版本覆盖了冲突文件,这些文件现在是“已修改”状态。同时,本地新增的文件(在步骤 3 中已git add .git commit)在合并过程中会被视为本地分支的贡献。

# 将所有当前更改(包括被--theirs策略修改的文件和本地新增文件)标记为已解决并暂存
git add .

这一步会把所有被git checkout --theirs .修改的文件以及本地新增的文件都准备好进行提交。

6.3 检查状态

git status

此时,git status不再显示 “Unmerged paths”。所有文件应该都处于 “Changes to be committed” 状态。确认新增文件也在其中。

7. 完成合并提交

所有冲突都按本次策略解决后,就可以完成这次合并操作了。

git commit

Git 会打开一个文本编辑器,通常会预填一个合并提交信息,如 Merge remote-tracking branch 'origin/main'。这里可以直接保存并关闭编辑器,或者修改提交信息后保存关闭。

8. 最终检查

git status

输出应该是nothing to commit, working tree clean,表示所有内容都已提交,本地分支与远程同步(即,远程的更改已经合并到本地,且本地的修改被保留了)。

同时,用文件浏览器检查一下项目文件夹,确保:

后续操作

现在,本地文件夹已经是一个功能齐全的、与远程 GitHub 仓库关联的 Git 仓库了。

将来如果远程仓库有更新:

  1. 提交或暂存本地新改动:
    # 如果有新的本地改动
    git add .
    git commit -m "Local work before pulling updates"
    # 如果不想立即提交
    # git stash save "WIP: my local changes"
    
  2. 拉取远程更新: 可以使用 pull --rebase 以保持线性历史:
    git pull --rebase origin main
    # 也可以使用默认的合并策略
    # git pull origin main
    
  3. 应用暂存(如果之前用了stash):
    # git stash pop
    
  4. 解决可能的冲突: 如果pullstash pop产生冲突,手动解决,然后git add <resolved_files>git rebase --continue (如果用了pull --rebasestash pop后 rebase) 或git commit (如果用了pull且是 merge 策略)。