# git遇到的问题

1. 

 ```
On branch master
modified: themes/hugo-theme-bootstrap4-blog (modified content)
 ```

如果但是 `git status` 仍然显示 `modified`，提交好像没有把改动记录下来。

这是因为你修改的文件 **在一个子模块里**：

- `themes/hugo-theme-bootstrap4-blog` 是一个 **子模块**，也就是一个独立的 Git 仓库。
- 当你在父仓库里执行 `git add .`，Git 只会记录 **子模块的引用更新**（即子模块指向的 commit 变化），而不会自动提交子模块里的文件。
- 子模块必须独立提交。

换句话说：

- 父仓库只知道子模块的 **commit ID**。
- 子模块里有改动，必须进入子模块提交，然后父仓库才会记录新的 commit ID。

正确做法：

假设你的父仓库有一个子模块 `themes/hugo-theme-bootstrap4-blog`：

```
# 进入子模块
cd themes/hugo-theme-bootstrap4-blog

# 查看子模块状态
git status

# 添加并提交子模块里的修改
git add .
git commit -m "子模块修改内容"

# 推送子模块到远程
git push origin master

# 回到父仓库
cd ../..

# 更新父仓库对子模块的引用
git add themes/hugo-theme-bootstrap4-blog
git commit -m "更新子模块引用"
git push origin master
```

2. 
	
	```
   ![rejected]  master -> master (fetch first)
   error: failed to push some refs to '<https://github.com/S1-19027/source_blog>'
   hint: Updates were rejected because the remote contains work that you do not
   hint: have locally. This is usually caused by another repository pushing to
   hint: the same ref. If you want to integrate the remote changes, use
   hint: 'git pull' before pushing again.
   hint: See the 'Note about fast-forwards' in 'git push --help' for details.
   ```

   这个错误表明你尝试将本地的 master 分支推送到远程仓库，但远程仓库的 master 分支包含了你本地没有的提交（即远程分支比你的本地分支更新）。Git 默认拒绝这种非快进（non-fast-forward）的推送，以避免覆盖远程仓库的更改。

   解决方法
   拉取远程更改并合并

   1. 获取远程仓库的最新更新
      `git pull --rebase origin master`
      此命令会将远程仓库的更新应用到您的本地分支之上，确保您的本地仓库包含所有最新的更改。使用 --rebase 选项可以避免产生多余的合并提交记录，使提交历史更加清晰。

   2. 解决可能的合并冲突
        在拉取过程中，如果本地更改与远程更改发生冲突，Git 会提示您解决这些冲突。您需要手动编辑冲突的文件，选择保留的更改，并删除冲突标记。完成后，使用以下命令将解决冲突后的文件添加到暂存区： `git add .`
        然后，提交这些更改：
        `git commit -m "解决合并冲突"`

   3. 推送本地更改到远程仓库
        在确保本地分支包含了所有远程更新并解决了所有冲突后，您可以将本地更改推送到远程仓库：
        `git push origin master`

   4. 注意事项

       强制推送的风险：虽然可以使用 git push -f 强制推送本地更改覆盖远程仓库的内容，但这种方法可能会导致他人的工作被覆盖，通常不推荐使用。

      保持本地仓库与远程仓库同步：为了减少冲突，建议在开始新的工作之前，先使用 git pull 获取远程仓库的最新更新，确保本地仓库与远程仓库保持同步。
        通过以上步骤，您可以在不覆盖本地工作目录的情况下，将本地更改成功推送到远程仓库。

3. `git pull`直接覆盖问题

​	git pull会把本地未提交修改覆盖。

​	Git 会尝试做两件事：  
​		1. `git fetch`：从远程仓库拉取最新 commit  
​		2. `git merge`：把远程的最新 commit 合并到你当前分支

​	如果你本地有 **未提交的修改**，Git 就有可能遇到冲突，或者直接拒绝 pull：

​	`Your local changes to the following files would be overwritten by` 

​	处理的方式非常简单，主要是使用git stash命令进行处理，分成以下几个步骤进行处理。

1. 先将本地修改存储起来
   git stash
   这样本地的所有修改就都被暂时存储起来 。是用git stash list可以看到保存的信息：
   git stash暂存修改
   其中stash@{0}就是刚才保存的标记。

2. pull内容
   暂存了本地修改之后，就可以pull了。

3. 还原暂存的内容
   ` git stash pop stash@{0}`

    系统提示如下类似的信息：
   `Auto-merging c/environ.c
   CONFLICT (content): Merge conflict in c/environ.c` 意思就是系统自动合并修改的内容，但是其中有冲突，需要解决其中的冲突。

4. 解决文件中冲突的的部分

   打开冲突的文件，会看到类似如下的内容：

   ```
   <<<<<<< Updated upstream
   远程 pull 下来的内容
   =======
   本地 stash 的内容
   >>>>>>> Stashed changes
   ```

   

   碰到这种情况，git也不知道哪行内容是需要的，所以要自行确定需要的内容。

   解决完成之后，就可以正常的提交了。

   总之

   分两种情况：

   1. 无冲突，本地未提交修改不会被覆盖，能够执行pull。

   2. 有冲突时，提示“Your local changes to the following files would be overwritten by merge”，本次pull执行失败，并且不会拉取远程代码，不用担心。

6. 
   fatal: refusing to merge unrelated histories

   这是因为 Git 检测到你本地分支和远程分支的提交历史是完全独立的（没有共同的祖先），Git 默认会拒绝合并这种不相关的历史记录。

   1. 允许合并不相关的历史记录

      在 git pull 或 git merge 时，添加 --allow-unrelated-histories 参数，强制 Git 合并不相关的历史记录。
      git pull origin master --allow-unrelated-histories
      执行完这条命令后，Git 会尝试将远程分支的历史记录与本地分支合并。如果有冲突，你需要手动解决冲突，然后提交合并结果。 **适合需要保留本地修改的情况**。

   2. 强制覆盖本地历史

      如果你确定远程仓库的内容是你想要的，而本地的提交历史可以丢弃，你可以先将本地分支重置到远程分支的状态：
      git fetch origin
      git reset --hard origin/master
      注意：这种方法会丢弃本地所有未推送的提交，请确保你不需要这些更改

   3.  重新初始化本地仓库

      如果你本地的提交历史不重要，可以删除本地的 .git 文件夹（这会删除本地 Git 仓库），然后重新克隆远程仓库：

      ```
      cd /f/p9/blog
      
      rm -rf .git
      
      git clone https://github.com/S1-19027/source_blog.git.
      ```

      注意：这种方法会完全覆盖本地仓库，请确保你已经备份了重要的更改。

8. 你执行了：

```
git pull origin master --allow-unrelated-histories
```

Git 报错：

```
error: Pulling is not possible because you have unmerged files.
hint: Fix them up in the work tree, and then use 'git add/rm <file>'
fatal: Exiting because of an unresolved conflict.
```

- 说明在 pull 的过程中 Git 尝试合并远程和本地提交时 **产生了冲突**
- 这些冲突还没解决，所以 **Git 不允许继续 pull 或 push**

然后你执行：

```
git push origin master
```

- **冲突文件没有被标记为已解决**
- Git 显示 `Everything up-to-date`，这是因为 **远程 master 的 HEAD 和本地提交（未合并的提交）在 Git 眼里并没有新的 commit**
- 也就是说，本地有冲突，但没有完成 commit，所以 Git push 认为没有新的 commit 要推送

步骤 A：检查冲突文件

```
git status
```

你会看到类似：

```
both modified: file1.txt
both added: file2.txt
```

- `both modified` 表示该文件在本地和远程都有修改，冲突未解决

步骤 B：手动解决冲突

1. 手动修改内容，保留你想要的版本

2. 保存文件

步骤 C：标记冲突已解决

```
git add <冲突文件>
```

- 注意必须是解决冲突后的文件
- `git add .` 可以一次性标记所有冲突文件已解决

步骤 D：提交合并结果

```
git commit -m "Resolve merge conflicts"
```

- 这条 commit 就是合并远程和本地的结果
- 只有完成 commit 后，本地才有新提交可推送

步骤 E：推送到远程

```
git push origin master
```

- 现在 push 会成功，因为本地有新的合并 commit

9. 我想要撤回我上传github（push）的操作如何做到
   要撤回已经上传（push）到 GitHub 的代码提交，Git 提供了几种常用的方法来实现这一目标。以下是详细的步骤和不同方法的解释，适用于不同的需求。

 	1. `git reset` + 强制推送

查看历史，找到你要回退到的提交：

```
git log
```

回退到指定提交（选择模式）：

- `--soft`：撤销提交，但保留改动在暂存区（方便修改后重新提交）
- `--mixed`（默认）：撤销提交并取消暂存，但保留本地修改
- `--hard`：撤销提交并删除本地修改（彻底回退）

```
git reset --hard <commit_id>
```

强制推送到远程覆盖历史：

```
git push origin <branch_name> --force
```

2. git revert

   查看提交历史：

   ```
   git log
   ```

   撤销某个提交：

   ```
   git revert <commit_id>
   ```

   - Git 会生成一个新提交，把指定 commit 的改动“反向应用”
   - 如果有冲突，手动解决后再 `git commit`

   推送到远程：

   ```
   git push origin <branch_name>
   ```

3. `git reflog` + 回退

查看历史操作记录：

```
git reflog
```

找到目标提交的 hash，回退：

```
git reset --hard <commit_hash>
```

强制推送覆盖远程：

```
git push origin <branch_name> --force
```

4. `git push --force-with-lease`

- **比 `--force` 更安全**的强制推送方式
- 会检查远程分支有没有被别人更新，如果远程有新提交，会阻止覆盖，避免冲突

```
git push origin <branch_name> --force-with-lease
```

| 场景                         | 推荐方法                       | 风险                  |
| ---------------------------- | ------------------------------ | --------------------- |
| 个人项目，需要彻底回退       | `git reset --hard` + `--force` | 高，会覆盖远程历史    |
| 团队协作，需要撤销某个提交   | `git revert`                   | 安全，不改变历史      |
| 不确定提交丢失，想恢复历史   | `git reflog` + `--force`       | 中等，需要小心        |
| 撤回提交，但避免覆盖别人工作 | `--force-with-lease`           | 安全性比 `--force` 高 |

9. `Error: fatal: Fetched in submodule path 'themes/hugo-theme-bootstrap4-blog', but it did not contain b410...
   Direct fetching of that commit failed.`

​	意思是：

- 父仓库引用的子模块提交 **b410…** 在远程子模块仓库里不存在
- Git 在拉取子模块时找不到这个 commit，所以报错
- 导致整个父仓库的 `git clone --recursive` 或 `git submodule update` 失败

1. 更新子模块引用

进入子模块：

```
cd themes/hugo-theme-bootstrap4-blog
```

拉取远程最新提交：

```
git fetch origin
git checkout master  # 或其他分支
git pull origin master
```

获取最新 commit：

```
git rev-parse HEAD
```

回到父仓库更新引用：

```
cd ../..
git add themes/hugo-theme-bootstrap4-blog
git commit -m "Update submodule to latest commit"
git push origin master
```

2. 重新初始化子模块

```
rm -rf themes/hugo-theme-bootstrap4-blog
git submodule update --init --recursive
```

- 可以清理掉错误的子模块目录，重新拉取

$ git pull origin master
From <https://github.com/S1-19027/source_blog>

3. 如果你对子模块没有权限 push，本地提交不会同步到远程，但父仓库可能已经引用了这个本地 commit，就会导致拉取失败。

   在父仓库中执行：

   ```
   cd themes/hugo-theme-bootstrap4-blog
   git log --oneline
   git remote -v
   ```

   - 查看你本地子模块的最新 commit
   - 查看远程地址是否有权限 push
   - 尝试手动 push 子模块：

   ```
   git push origin master
   ```

   如果提示权限错误或拒绝推送，那就证实了问题。

   **使用 Fork 或自己有权限的仓库**

   1. 在 GitHub 上 **fork** 子模块仓库
   2. 修改父仓库中子模块的 URL 指向你的 fork：

   ```
   git config -f .gitmodules submodule.themes/hugo-theme-bootstrap4-blog.url <你的 fork 地址>
   git submodule sync
   ```

   1. 然后在你的 fork 仓库 push 子模块提交：

   ```
   cd themes/hugo-theme-bootstrap4-blog
   git push origin master
   ```

   1. 更新父仓库中子模块引用：

   ```
   cd ../..
   git add themes/hugo-theme-bootstrap4-blog
   git commit -m "Update submodule to my fork commit"
   git push origin master
   ```

   > 这样就不会依赖你对原仓库的权限，同时可以正常推送和拉取。