跳转至

Git

github push

git push

  • 正常推送:仅在远程分支没有新的提交且你的本地分支包含所有远程分支的最新提交时,推送才会成功。(提交消息不能落后,代码状态不能落后)
  • 推送失败情况:如果远程分支有新的提交,推送会被拒绝,提示你先获取(pull)最新的远程提交。

git push --force-with-lease

  • 强制推送:允许你覆盖远程分支的历史,但在进行强制推送之前会检查远程分支的状态。(提交消息可以落后,代码状态不能落后)
  • 更安全的强制推送:只有在远程分支的状态与你本地分支在准备推送时看到的状态一致时,才会执行强制推送。如果远程分支在你准备推送的过程中被其他人更新,推送操作将会被拒绝。

--force-with-lease

  • 如果amend last commit,修改了历史提交消息。此时本地分支的提交历史落后于远程分支的提交历史,就需要使用--force-with-lease来安全地强制推送,它会在推送之前检查远程分支的最新提交是否与本地分支在准备推送时的预期状态一致。(只是修改了提交消息,提交消息落后,但是代码状态没有落后,能成功)
  • 如果远程分支在你准备推送的过程中被更新,推送会被拒绝,以避免覆盖其他人的工作。(代码状态落后,会失败)

(github不允许对受保护分支使用强制推送,需要修改分支保护规则)

pull

git强制覆盖本地代码(与git远程仓库保持一致)

git pull origin dev -f # dev为远程分支名

fetch

cherry-pick

git cherry-pick 教程 - 阮一峰的网络日志

首先在自己本地开发的dev分支,pull rebase一下,确保最新

  • 有些不想提交的文件,切换分支前先stash pop,切回来后再stash pop,包括combine to one commit时出现this task requires a clean working tree时也需要

1、基于远程最新dev分支创建本地feature分支,

2、dev_feature都不要主动修改,使用cherry pick,然后解决冲突**(出现冲突时,都以功能分支的内容为准)**

TortoiseGit 如何使用 cherry-pick_tortoisegit cherry pick-CSDN博客

3、然后可以选中几个提交记录,一起合并

4、可以善用revert dev to this,可以在pull之后时候,让一个commit的代码保存在本地,但是留有未跟踪状态

其他问题

1、git merge和cherry pick选择

选择 git merge 还是 git cherry-pick 取决于你的具体需求和工作流程。下面是这两种方法的区别以及何时使用它们:

git merge

适用场景:

  • 合并完整的分支历史:当你希望将一个分支上的所有更改(包括所有提交历史)合并到另一个分支时,使用 git merge
  • 保持分支历史的完整性:合并操作会保留分支的所有提交历史,并在目标分支上创建一个新的合并提交。

操作步骤:

  1. 切换到目标分支
git checkout main
  1. 合并源分支
git merge feature-branch
  1. 解决冲突(如果有)
# 编辑冲突文件,解决冲突
git add <conflicted-file>
git commit
  1. 推送更改(如果需要)
git push origin main

git cherry-pick

适用场景:

  • 选择性地应用提交:当你只希望将某些特定的提交从一个分支应用到另一个分支时,使用 git cherry-pick
  • 避免合并所有更改:如果你不需要合并整个分支的历史,只需要某些特定的提交,可以使用 git cherry-pick

操作步骤:

  1. 找到你要应用的提交哈希值
  2. 使用 git log 查看提交历史,并找到你要应用的提交哈希值。
git log feature-branch
  1. 切换到目标分支
git checkout main
  1. 应用特定的提交
git cherry-pick <commit-hash>
  1. 解决冲突(如果有)
# 编辑冲突文件,解决冲突
git add <conflicted-file>
git cherry-pick --continue
  1. 推送更改(如果需要)
git push origin main

2、我的代码在上一次commit,已经commit了全部的已更改。但是我现在需要一步一步来,要怎么办,只提交某些文件中的某些代码

如果你已经提交了所有的更改,但现在需要一步一步地提交某些文件中的某些代码,你可以使用 git resetgit add -p 来实现。以下是详细步骤:

1. 回退到上一个提交

首先,回退到上一个提交状态,将所有更改放回工作目录:

git reset HEAD~1

这会将上一次提交的更改取消,并将这些更改放回暂存区和工作目录。

2. 逐步添加更改

使用 git add -p 来逐步添加更改。这个命令会交互式地让你选择要暂存的代码块:

git add -p

Git 会显示每个代码块,并询问你是否要暂存该块。你可以输入以下选项:

  • y:暂存这个块。
  • n:不暂存这个块。
  • q:退出,停止暂存。
  • a:暂存这个块及其余所有块。
  • d:不暂存这个块及其余所有块。
  • s:拆分当前块成更小的块。
  • e:手动编辑当前块。
  • ?:显示帮助。

通过这种方式,你可以选择性地暂存某些文件中的某些代码块。

3. 提交暂存的更改

在选择性地暂存了你想要的更改后,提交这些更改:

git commit -m "Your commit message"

4. 重复步骤 2 和 3

重复步骤 2 和 3,直到你将所有需要的更改逐步提交完毕。

示例步骤

以下是一个完整的示例流程:

  1. 回退到上一个提交

    git reset HEAD~1
    
  2. 逐步添加更改

    git add -p
    

    选择你想要暂存的代码块。

  3. 提交暂存的更改

    git commit -m "First part of the changes"
    
  4. 重复步骤 2 和 3,直到所有更改都被提交:

    git add -p
    git commit -m "Second part of the changes"
    
    git add -p
    git commit -m "Third part of the changes"
    

通过这种方式,你可以一步一步地提交某些文件中的某些代码。

5、Stash and continue to proceed without losing changes (changes will be reapplied after the checkout), or force checkout to overwrite all changes。vs切换分支时出现,这是什么意思

当你在 Visual Studio (VS) 或任何其他 Git 客户端中尝试切换分支时,如果当前工作目录中有未提交的更改,你可能会看到如下提示:

Stash and continue to proceed without losing changes (changes will be reapplied after the checkout), or force checkout to overwrite all changes.

这意味着你有两种选择来处理当前未提交的更改:

1. Stash Changes

Stash and continue to proceed without losing changes:这意味着你可以将当前的未提交更改暂存(stash)起来,然后切换分支。暂存的更改可以在你切换到新分支后重新应用。

步骤

  1. Stash 当前的更改

    • 在 VS 中,选择 "Stash and continue" 选项。
    • 或者在命令行中使用以下命令:
      git stash
      
  2. 切换分支

    • 在 VS 中,切换到你想要的分支。
    • 或者在命令行中使用:
      git checkout <branch_name>
      
  3. 重新应用暂存的更改

    • 在 VS 中,选择 "Apply Stash" 或类似选项。
    • 或者在命令行中使用:
      git stash pop
      

通过这种方式,你不会丢失任何未提交的更改。

2. Force Checkout

Force checkout to overwrite all changes:这意味着你可以强制切换分支,这会丢弃当前工作目录中的所有未提交更改。

步骤

  1. 强制切换分支
    • 在 VS 中,选择 "Force checkout" 选项。
    • 或者在命令行中使用以下命令:
      git checkout -f <branch_name>
      

这会丢弃你当前工作目录中的所有未提交更改,直接切换到目标分支。

选择哪种方式

  • 如果你不想丢失当前的更改,并且希望在切换分支后继续这些更改,选择 Stash and continue
  • 如果你确定当前的更改不再需要,可以选择 Force checkout 来丢弃这些更改并切换分支。

总结

  • Stash and continue:暂存当前更改,切换分支后重新应用这些更改。
  • Force checkout:丢弃当前更改,直接切换分支。

选择适合你当前需求的方式来处理未提交的更改。

10、Git failed with a fatal error. Git failed with a fatal error. Unable to process path src/.vs/myserver_2019/v16/Browse.VC.opendb Cannot save the untracked files,git切换分支,选择了stash and continue,但是出现了以上问题

当你在 Git 中尝试切换分支并选择 "stash and continue" 时遇到以下错误:

Git failed with a fatal error. Git failed with a fatal error. Unable to process path src/.vs/myserver_2019/v16/Browse.VC.opendb
Cannot save the untracked files

这通常是因为 Git 无法处理某些未被跟踪的文件。未被跟踪的文件是指那些还没有被添加到 Git 仓库中的文件(即没有被 git add 过)。

解决方法

以下是几种解决方法来解决这个问题:

1. 手动添加未被跟踪的文件

如果这些未被跟踪的文件是你希望保留的文件,你可以先将它们添加到暂存区,然后再进行 stash 操作:

git add src/.vs/myserver_2019/v16/Browse.VC.opendb
git stash
git checkout <branch_name>
git stash pop

2. 忽略未被跟踪的文件

如果这些未被跟踪的文件是一些不需要被版本控制的文件(例如,临时文件或生成的文件),你可以将它们添加到 .gitignore 文件中:

  1. 打开或创建 .gitignore 文件。
  2. 添加以下行来忽略这些文件:

    src/.vs/
    
  3. 然后再尝试 stash 和切换分支:

    git stash
    git checkout <branch_name>
    git stash pop
    

3. 强制 stash 忽略未被跟踪的文件

你可以使用 git stash -ugit stash --include-untracked 来包括所有未被跟踪的文件:

git stash -u
git checkout <branch_name>
git stash pop

总结

  • 手动添加未被跟踪的文件:如果这些文件需要被版本控制。
  • 忽略未被跟踪的文件:如果这些文件不需要被版本控制。
  • 强制 stash 忽略未被跟踪的文件:使用 git stash -u 包括所有未被跟踪的文件。

选择适合你当前情况的方法来处理这些未被跟踪的文件。

仓库管理

因为我是仓库管理员,所以即使我没有勾选“Do not allow bypassing the above settings”选项,我也能绕过”equire a pull request before merging“的branch规则,而其他人绕不过。

我勾选了“Do not allow bypassing the above settings”选项,管理员和其他人都无法绕过”equire a pull request before merging“的branch规则。

Collaborators

分配权限

  • 默认情况下,添加的协作者会被赋予 Write 权限。你可以通过点击他们名字旁边的权限级别选项来更改权限(例如 Read, Write, 或 Admin)。
  • Admin 权限允许协作者管理仓库设置和添加其他协作者。

权限级别

  • Read:只能查看仓库内容,不能进行修改。- Write:可以查看和修改仓库内容,包括推送代码、创建和合并 Pull Request,但不能绕过分支保护规则,即使“Do not allow bypassing the above settings”未勾选。
  • Admin:拥有仓库的所有权限,包括管理设置、保护分支、删除仓库等。如果“Do not allow bypassing the above settings”未勾选,他们可以绕过保护规则;如果勾选了,他们也无法绕过。

公有仓库与私有仓库

公共仓库

  • 任何人:任何拥有 GitHub 账户的用户都可以对公共仓库进行 Fork 操作,并基于 Fork 创建 Pull Request。
  • 步骤:
  • 用户 Fork 你的公共仓库。
  • 在他们自己的 Fork 中进行更改。
  • 提交更改并创建 Pull Request,目标仓库为你的公共仓库。

私有仓库

  • 被邀请的 Collaborators:只有被添加为 Collaborators 的用户才能访问和创建 Pull Request。
  • 外部贡献者:无法直接访问私有仓库,因此不能创建 Pull Request。

公有仓库的Collaborators和非Collaborators

Collaborators 的 Pull Request

  1. 权限
  2. Collaborators 对仓库有直接的写权限,可以直接推送更改到仓库的分支。
  3. 他们可以在仓库的主分支或其他受保护分支上工作,受保护分支的更改可能需要满足特定的审核和检查要求。
  4. 工作流程
  5. Collaborators 可以直接在仓库的分支上进行更改并提交 Pull Request。
  6. 他们的 Pull Request 通常会自动触发 CI/CD 流程,且可以在仓库的上下文中查看和管理。

非-Collaborators 的 Pull Request

  1. 权限
  2. 非-Collaborators 没有直接的写权限,无法直接推送更改到仓库的分支。
  3. 他们需要通过 Fork 仓库的方式来进行更改。
  4. 工作流程
  5. 非-Collaborators 首先 Fork 公共仓库,创建其副本。
  6. 在 Fork 仓库中进行更改并提交到他们自己的分支。
  7. 从 Fork 仓库创建 Pull Request,目标仓库为原始公共仓库。
  8. 他们的 Pull Request 也会触发 CI/CD 流程,但需要仓库维护者进行进一步的审核和合并。

补充

已删除远程分支,本地远程分支跟踪信息没更新

更新本地的远程跟踪分支信息

使用 git fetch 命令来更新本地的远程跟踪分支信息:

git fetch -p

其中,-p--prune 选项会删除本地已经不存在的远程分支的引用。

查看本地的远程跟踪分支

你可以使用以下命令查看本地的远程跟踪分支:

git branch -r

强制更新本地

比如在虚拟机上,拉取分支,并强制更新本地

git fetch origin #命令会更新所有远程追踪分支的信息。
git reset --hard origin/分支名 #命令会将当前分支的 HEAD、索引和工作目录都重置为指定的远程分支的状态,丢弃所有未提交的更改。

git fetch origin && git reset --hard origin/分支名

windows下设置git对大小写敏感

git config --global core.ignorecase false

git clone远程仓库的指定分支

git clone --branch(-b) <branch-name> <repository-url>

git clone网络太差总是失败

git clone 网络太差总是失败:error: RPC 失败。curl 92 HTTP/2 stream 5 was not closed cleanly: CANCEL (err 8)

❯ git clone https://github.com/Almamu/linux-wallpaperengine.git .
正克隆到 '.'...
remote: Enumerating objects: 6271, done.
remote: Counting objects: 100% (1447/1447), done.
remote: Compressing objects: 100% (628/628), done.
error: RPC 失败。curl 92 HTTP/2 stream 5 was not closed cleanly: CANCEL (err 8)
error: 预期仍然需要 6355 个字节的正文
fetch-pack: unexpected disconnect while reading sideband packet
fatal: 过早的文件结束符(EOF)
fatal: fetch-pack:无效的 index-pack 输出

解决方法

git clone http://github.com/大仓库.git --depth 1
cd 大仓库
git fetch --unshallow

分支落后

看你本地的分支是否有些东西落后于你要push的分支

  1. 直接push算一次提交
  2. pull request算一次提交

所以:

我本地仓库更改了,然后本地分支push到了dev_asus分支,接着dev_asus分支pull request到dev分支;之后再想本地分支直接push force到dev分支,会失败

因为dev分支有这个pull request提交,而本地分支没有这个提交记录,导致远程dev分支领先于本地分支,因此失败。

git pull -rebase什么作用,TortoiseGit 的“Launch Rebase after Fetch”

就是有人将远程仓库更新了,我就得这么做,如果有人出现冲突,直接在tortoiseGit里解决冲突,然后marked as resolve

git pull --rebase 是 Git 中的一个命令,用于从远程仓库拉取最新的更改并将这些更改应用到你的本地分支上,同时使用 rebase 而不是默认的 merge 方式来整合这些更改。它的主要作用和好处如下:

作用

  1. 拉取远程更改
  2. 从远程仓库获取最新的提交和更改。

  3. 重写本地提交历史

  4. 将远程分支的更改应用到你的本地分支上,同时将你的本地提交“重新应用”到这些更改之上。具体来说,它会先将你的本地提交临时保存(即“摘下”),然后将远程提交应用到本地分支,最后再将你的本地提交一个一个地重新应用到更新后的分支上。

使用场景

  • 保持提交历史的整洁
  • 使用 git pull --rebase 可以避免产生不必要的合并提交(merge commit),从而保持提交历史的线性和整洁。

  • 同步团队工作

  • 当多个开发者在同一个分支上工作时,使用 git pull --rebase 可以减少合并冲突,并确保每个开发者的提交都“顺序”应用到主分支上。

示例

假设你正在 feature 分支上工作,并且你的本地分支已经有一些提交。与此同时,远程的 feature 分支也有一些新的提交。执行 git pull --rebase 的过程如下:

  1. 当前状态
  2. 本地分支有提交 ABC
  3. 远程分支有提交 DE

  4. 执行 git pull --rebase

    git pull --rebase origin feature
    

  5. 操作顺序

  6. Git 会首先将你的本地提交 ABC 摘下(暂存)。
  7. 然后,它会将远程的提交 DE 应用到你的本地分支。
  8. 最后,Git 会将你的本地提交 ABC 重新应用到 DE 之后。

  9. 结果

  10. 你的本地分支将会有提交 DEABC,而没有产生额外的合并提交。

注意事项

  • 冲突处理
  • rebase 过程中遇到冲突时,Git 会暂停并提示你解决冲突。你需要手动解决冲突,然后使用 git rebase --continue 继续 rebase 过程。

  • 避免在公共分支上使用

  • 对于已经推送到远程仓库的公共分支(如 mainmaster),避免使用 rebase,因为它会重写提交历史,可能会导致其他开发者的工作混乱。对于公共分支,通常推荐使用 merge

总结

git pull --rebase 是一个强大的命令,能够帮助你保持提交历史的线性和整洁,同时减少合并冲突。在团队协作中,它可以让每个开发者的提交顺序应用到主分支上,从而简化代码集成过程。然而,在使用时需要注意冲突处理和避免在公共分支上使用。

区别和联系

  1. 自动化程度

    • git pull --rebase 是一个单一的命令,自动完成 fetchrebase 两个步骤。
    • TortoiseGit 的“Launch Rebase after Fetch”是一个选项,当你执行 fetch 操作时,它会提示你是否要进行 rebase,让用户有更多的控制权。
    • 用户交互

    • git pull --rebase 是一个命令行操作,适合熟悉 Git 命令的用户。

    • TortoiseGit 提供了图形用户界面,适合喜欢 GUI 操作的用户,并且在 fetch 之后会有提示,用户可以选择是否进行 rebase
    • 使用场景

    • git pull --rebase 适合那些希望在每次拉取远程更改时自动进行 rebase 的用户,通常在脚本或命令行环境中使用。

    • TortoiseGit 的选项适合那些希望在执行 fetch 后有更多控制权的用户,尤其是在图形界面中操作时。

.gitignore

通配符

在通配符模式中,*** 是两个不同的通配符,它们在匹配文件和目录时具有不同的含义。

  • *(星号):匹配零个或多个字符(不包括目录分隔符)。例如,*.txt 可以匹配所有以 .txt 结尾的文件名。

  • **(双星号):匹配零个或多个目录和子目录。它可以用于递归匹配任意深度的目录结构。例如,src/**/file.txt 可以匹配 src 目录下的任意深度的子目录中的 file.txt 文件。

在上面提到的例子中,thirdparty/*/out/ 使用了 * 通配符来匹配一个目录级别,它只匹配 thirdparty 目录下的一级子目录中的 out 文件夹。而 thirdparty/**/out/ 使用了 ** 通配符来匹配任意深度的子目录,它匹配 thirdparty 目录下的所有子目录中的 out 文件夹,无论子目录的深度如何。

因此,* 用于匹配单个目录级别或文件名,而 ** 用于匹配任意深度的目录结构。

获取指定tag的代码

要从远程仓库下载指定标签(tag)的代码,可以使用 Git 提供的命令来完成。以下是具体步骤:

1. 克隆远程仓库

首先,克隆远程仓库到本地。如果你还没有克隆仓库,可以使用以下命令:

git clone <repository_url>

例如:

git clone https://github.com/user/repository.git

2. 列出所有标签

如果你不确定要使用哪个标签,可以列出所有标签:

cd repository
git tag

这将显示所有可用的标签。

3. 检出指定标签

使用 git checkout 命令检出指定的标签。假设你要检出的标签是 v1.0

git checkout tags/v1.0 -b my-branch

这里,tags/v1.0 是你要检出的标签名,-b my-branch 是创建一个新的分支 my-branch,并在该分支上检出标签的代码。这是因为直接检出标签会使 HEAD 处于“分离头”状态,创建一个新分支可以避免这种情况。

4. 直接克隆特定标签(可选)

如果你不需要克隆整个仓库,而只需要特定标签的代码,可以使用以下命令:

git clone --branch <tag_name> --single-branch <repository_url>

例如:

git clone --branch v1.0 --single-branch https://github.com/user/repository.git

这将只克隆标签 v1.0 的代码。

示例

以下是一个完整的示例,展示如何从头开始下载远程仓库并检出指定标签的代码:

# 克隆远程仓库
git clone https://github.com/user/repository.git

# 进入仓库目录
cd repository

# 列出所有标签
git tag

# 检出指定标签并创建新分支
git checkout tags/v1.0 -b my-branch

或者,直接克隆特定标签的代码:

git clone --branch v1.0 --single-branch https://github.com/user/repository.git

通过这些步骤,你可以方便地下载远程仓库中指定标签的代码。