17611538698
webmaster@21cto.com

干货 Git 指南

编程语言 0 110 2024-04-18 03:39:12

图片

导读:一篇送给大家的实用干货Git指南,可以收藏常备。

俗话说:

🩺 医生有听诊器。
🔧 机械师有扳手。
👨‍💻 我们开发者有 Git。

不知道各位是否注意到, Git 对于编码工作来说是如此地不可或缺,以至于我们几乎从未将其包含在自己自己的技术堆栈或简历中。

Git 是一个版本控制系统(VCS),使我们能够存储、更改代码并与其他兄弟姐妹协作。

作为开发者,我们的日常工作围绕着阅读、编写和审查代码为主。Git 可以说是我们使用的最重要的工具之一。作为一名开发人员,掌握 Git 提供的特性和功能是我们对自己进行的最佳投资之一。

让我们开始~

图片

让我们把基础打好


Git 有没有让你感觉像 Peter Griffin 一样?


如果没有以正确的方式学习 Git,你可能会不断地摸不着头脑,陷入同样的问题,或者后悔有一天在终端中出现另一个合并冲突。让我们定义一些基本的 Git 概念来确保这种情况不会发生。


图片

分支


在 Git 存储库中,你会发现一条开发主线,通常名为“main”或“master”(后来已弃用),其中有几个分支。这些分支代表同时的工作流,使开发者能够在同一项目中同时处理多个功能或修复。


图片

提交


Git 提交作为更新代码的捆绑包,捕获项目代码在特定时间点的快照。每次提交都会记录自上次记录以来所做的更改,共同构建项目开发旅程的全面历史。

图片

当引用提交时,你通常会使用其唯一标识的加密哈希。

例子:

git show abc123def456789
这显示了有关该哈希提交的详细信息。


标签


Git标签充当 Git 历史中的地标,通常标记项目开发中的重要里程碑,例如releases、versions或standout commits。这些标签对于标记特定时间点非常有价值,通常代表项目旅程中的起点或主要成就。


图片

HEAD

当前签出分支上的最新提交由 指示HEAD,用作指向存储库中任何引用的指针。

当你位于特定分支时,HEAD指向该分支上的最新提交。有时,HEAD可以直接指向特定的提交(detached HEAD状态),而不是指向分支的顶端。

阶段


了解 Git 阶段对于导航 Git 工作流程非常重要。它们代表文件更改在提交到存储库之前发生的逻辑转换。

让我们深入研究一下 Git 阶段的概念:

图片

工作目录👷


我们的working directory工作目录,表示可以在其中编辑、修改和创建项目文件。也同时表示本地计算机上文件的当前状态。


暂存区🚉


该staging区域就像一个保留区域或预提交区域,你可以在其中准备更改,然后再将更改提交到存储库。

这里有用的命令:git add
也可以使用git rm用于取消暂存更改


本地存储库🗄️


本地存储库是 Git 永久存储已提交更改的位置。它允许你查看项目的历史记录,恢复到以前的状态,并与同一代码库上的其他人进行协作。

可以使用以下命令提交暂存区域中准备好的更改:git commit

远程存储库🛫


远程(远端)存储库是一个集中位置,通常托管在服务器(例如 GitHub、GitLab 或 Bitbucket)上,你可以在其中与其他人共享项目并进行协作。

可以使用git push和等命令git pull将提交的更改从本地存储库推送/拉取到远程存储库。


Git 入门


好吧,你必须从某个地方开始。

而在 Git 中,那就是你的workspace,我们可以fork或clone现有存储库并拥有该工作区的副本,或者如果你在计算机上的新本地文件夹中完全全新开始,则必须将其转换为带有git init命令。

图片

凭证设置


当运行推送和拉取到远程存储库时,我们并不想每次都输入用户名和密码,只需执行以下命令即可避免这种情况:

git config --global credential.helper store

当第一次与远程存储库交互时,Git 会提示您输入用户名和密码。之后,我们将不会再收到提示。

请务必注意,凭据以纯文本格式存储在.git-credentials文件中。

要检查配置的凭据,您可以使用以下命令:

git config --global credential.helper


与分支协作


在本地工作时,了解当前所在的分支至关重要。这些命令将很有帮助:


# Will show the changes in the local repository
git branch
# Or create a branch directly withgit branch feature-branch-name


要在分支之间转换,请使用:

git switch

除了在它们之间进行转换之外,您还可以使用:

git checkout # A shortcut to switch to a branch that is yet to be created with the -b flag git checkout -b feature-branch-name

要检查存储库的状态,请使用:

git status

始终清楚地了解当前分支的一个好方法是在终端中查看它。许多终端插件可以帮助解决这个问题。

下面的就是一个。

图片

使用提交


在处理提交时,使用 git commit -m 记录更改,使用 git amend 修改最近的提交,并尽力遵守提交消息约定。


# Make sure to add a message to each commit
git commit -m "meaningful message"


如果你对上次提交进行了更改,则不必完全创建另一个提交,可以使用 --amend 标志来使用分阶段更改来修改最近的提交:

# make your changesgit add .git commit --amend# This will open your default text editor to modify the commit message if needed.git push origin your_branch --force

⚠️ 使用时要小心--force,因为它有可能覆盖目标分支的历史记录,通常应避免在 main/master 分支上应用它。

根据经验,最好经常提交,以避免丢失进度或意外重置未暂存的更改。之后可以通过压缩多个提交或进行交互式改变基线来重写历史记录。

用于git log显示按时间顺序排列的提交列表,从最近的提交开始并按时间倒推:

操作历史


操作历史涉及一些强大的命令。Rebase重写提交历史记录,Squashing将多个提交合并为一个,并Cherry-picking选择特定提交。


变基和合并


将变基与合并进行比较是有意义的,因为它们的目标相同,但实现方式不同。


二者关键的区别在于变基重写了项目的历史。对于重视清晰且易于理解的项目历史的项目来说,这是理想的选择。另一方面,合并通过生成新的合并提交来维护两个分支历史记录。


在变基期间,功能分支的提交历史记录在移至HEAD主分支时会被重组:

图片

这里的工作流程变得非常简单。

确保你位于要变基的分支上并从远程存储库获取最新更改:

git checkout your_branchgit fetch

现在选择你想要变基的分支并运行以下命令:

git rebase upstream_branch

变基后,如果分支已推送到远程存储库,您可能需要强制推送更改:

git push origin your_branch --force


⚠️ 使用时要小心--force,因为它有可能覆盖目标分支的历史记录。通常应避免在 main/master 分支上应用它。

push

Git push用于将多个提交压缩为单个、有“凝聚力”的提交。

图片

这个概念很容易理解,如果使用的统一代码的方法是变基,则非常有用,因为历史记录会被改变,所以注意对项目历史记录的影响很重要。

有时很难执行push,特别是使用交互式变基,幸运的是,我们有一些工具可以帮助自己。以下是我首选的压缩方法,其中涉及将 HEAD 指针向后移动 X 次提交,同时保留分阶段的更改。

# Change to the number after HEAD~ depending on the commits you want to squashgit reset --soft HEAD~Xgit commit -m "Your squashed commit message"git push origin your_branch --force

⚠️ 使用时要小心--force,因为它有可能覆盖目标分支的历史记录。通常应避免在 main/master 分支上应用它。

cherry pick

cherry pick 对于有选择地将更改从一个分支合并到另一个分支非常有用,特别是当合并整个分支不合需要或不可行时。

然而,明智地使用cherry选择很重要,因为如果应用不当,可能会导致重复提交和不同的历史记录:

图片

要首先执行此操作,你必须确定您想要选择提交的哈希,可以使先操作git log。一旦确定了提交哈希,然后就可以运行:

git checkout target_branchgit cherry-pick  # Do this multiple times if multiple commits are wantedgit push origin target_branch


高级 Git 命令


签名提交


对提交进行签名是一种验证 Git 中提交的真实性和完整性的方法。它允许您使用 GPG (GNU Privacy Guard) 密钥对您的提交进行加密签名,从而向 Git 保证您确实是该提交的作者。您可以通过创建 GPG 密钥并将 Git 配置为在提交时使用该密钥来实现此目的。


步骤如下:

# Generate a GPG keygpg --gen-key
# Configure Git to Use Your GPG Keygit config --global user.signingkey
# Add the public key to your GitHub account
# Signing your commits with the -S flaggit commit -S -m "Your commit message"
# View signed commitsgit log --show-signature


Git 引用日志


我们还没有探讨的一个主题是 Git 引用,它们是指向存储库中各种对象的指针,主要是提交,还有标签和分支。它们充当 Git 历史记录中的命名点,允许用户浏览存储库的时间线并访问项目的特定快照。了解如何导航 git 引用非常有用,他们可以使用 git reflog 来做到这一点。


以下是一些好处:

  • 恢复丢失的提交或分支

  • 调试和故障排除

  • 纠正错误


交互式变基


交互式变基是一个强大的 Git 功能,允许您以交互方式重写提交历史记录。它使您能够在将提交应用到分支之前对其进行修改、重新排序、组合或删除。

为了使用它,你必须熟悉可能的操作,例如:

  • pick(“p”)

  • reword(“r”)

  • edit(“e”)

  • squash(“s”)

  • delete(“d”)

图片

这是一个有用的视频,用于学习如何在终端中执行交互式变基,我还在博客文章的底部链接了一个有用的工具。

与 Git 协作


起源与上游


源是克隆本地 Git 存储库时与本地 Git 存储库关联的默认远程存储库。如果你分叉了一个存储库,那么默认情况下该分叉将成为你的“原始”存储库。


另一方面,上游指的是你的存储库分叉的原始存储库。


为了使你的分叉存储库与原始项目的最新更改保持同步,可以使用git fetch从“上游”存储库进行更改,并将它们合并或变基到本地存储库。

# By pulling the pulled changes will be merged into your working branchgit pull  # If you don't want to merge the changes usegit fetch 

要查看与本地 Git 存储库关联的远程存储库,请运行:

git remote -v


冲突

不要惊慌,当尝试合并或变基分支并检测到冲突时,这只意味着存储库中同一文件或文件的不同版本之间存在冲突的更改,并且都可以轻松解决。

图片

它们通常在受影响的文件中指示,Git 在其中插入冲突标记<<<<<<<,=======并>>>>>>>突出显示冲突部分。

决定保留、修改或删除哪些更改,确保生成的代码有意义并保留预期的功能。

手动解决冲突文件中的冲突后,删除冲突标记<<<<<<<、=======和 ,>>>>>>>并根据需要调整代码。

对解决方案感到满意后,保存冲突文件中的更改。

流行的 Git 工作流程

图片

现实中存在各种 Git 工作流程,但需要注意的是,不存在通用的“最佳”Git 工作流程。相反,每种方法都有其自身的优点和缺点。让我们探索这些不同的工作流程,以便来了解它们的优点和缺点。

图片

功能分支工作流程🌱


每个新功能或错误修复都是在自己的分支中开发的,然后在完成后将其合并回主分支。

  • 优点:隔离变更并减少冲突。

  • 弱点:可能变得复杂并且需要勤奋的分支机构管理。

Gitflow 工作流程 🌊


Gitflow 定义了严格的分支模型,为不同类型的开发任务提供了预定义的分支。


它包括长期分支,例如 main、develop、feature 分支、release 分支和 hotfix 分支。

  • 优点:适合定期发布、长期维护的项目。

  • 缺点:对于较小的团队来说可能过于复杂

分叉工作流程🍴


在此工作流程中,每个开发人员都会克隆主存储库,但他们不会将更改直接推送到主存储库,而是将更改推送到自己的存储库分支。然后,开发人员创建拉取请求以提出对主存储库的更改,从而允许在合并之前进行代码审查和协作。


这是我们在开源 Glasskube 存储库上进行协作的工作流程。

  • 优点:鼓励外部贡献者进行协作,而无需授予对主存储库的直接写入访问权限。

  • 弱点:维持分支和主存储库之间的同步可能具有挑战性。

拉取请求工作流程 ⏩


与分叉工作流程类似,但开发人员不是分叉,而是直接在主存储库中创建功能分支。

  • 优点:促进团队成员之间的代码审查、协作和知识共享。

  • 弱点:对人类代码审查员的依赖可能会导致开发过程延迟。

基于主干的开发🪵


如果你所在的团队专注于快速迭代和持续交付,你可能会使用基于主干的开发,开发人员直接在主分支上工作,提交小而频繁的更改。

  • 优势:促进快速迭代、持续集成,并专注于为生产提供小而频繁的变更。

  • 缺点:需要强大的自动化测试和部署管道来确保主分支的稳定性,可能不适合发布时间表严格或功能开发复杂的项目。

什么是分叉?


强烈建议在开源项目上进行分叉,这样可以完全控制自己的存储库副本。你可以进行更改、尝试新功能或修复错误,而不会影响原始项目。

💡 我花了很长时间才弄清楚,虽然分叉存储库作为单独的实体开始,但它们保留了与原始存储库的连接。此连接允许你跟踪原始项目中的更改,并将自己的分支与其他人所做的更新同步。

这就是为什么即使你推送到原始存储库也是如此。

奖品:Git 命令备忘录

# Clone a Repositorygit clone 
# Stage Changes for Commitgit add
# Commit Changesgit commit -m "Commit message"
# Push Changes to the Remote Repositorygit push
# Force Push Changes (use with caution)git push --force
# Reset Working Directory to Last Commitgit reset --hard
# Create a New Branchgit branch
# Switch to a Different Branchgit checkout
# Merge Changes from Another Branchgit merge
# Rebase Changes onto Another Branch (use with caution)git rebase
# View Status of Working Directorygit status
# View Commit Historygit log
# Undo Last Commit (use with caution)git reset --soft HEAD^
# Discard Changes in Working Directorygit restore
# Retrieve Lost Commit Referencesgit reflog
# Interactive Rebase to Rearrange Commitsgit rebase --interactive HEAD~3
# Pull changes from remote repogit pull
# Fetch changes from remote repo git fetch


如果你觉得我错过了或应该更详细地了解特定命令,请在下面的评论中告诉我。我将相应地更新这篇文章。

如果喜欢此类文章并希望看到更多内容,请给我们点赞、转发以及请喝咖啡,支持我们!

作者:校长

评论