Manaswini Das 发布的文章

这些文章包含了黑科技、鲜为人知的事实,以及在使用 Git 时可以派上用场的技巧和窍门。

 title=

Git 是代码协作开发工作流程中不可或缺的一部分。无论你是初学者还是专家,第一件事就是在使用开源代码时需要学习这个功能强大的版本控制系统。对于 Git,不需要知道所有事情,但是了解一些特殊的黑科技可以让你在 GitLab 等平台上更轻松地分享代码,因此你可以与不同地方的开发人员协作。如果有什么没把握的地方,git --help 可以帮助你。

我每天都为了解 Git 所提供的控制能力而感到惊讶。没有哪种情况是你无法恢复到早期版本的,无论你所处的情况是多么不可能或棘手。

在 2021 年我们发布了大量 Git 的文章;我只汇总了其中前 10 篇,这些文章包含了各种黑科技、鲜为人知的事实,以及在使用 Git 时可以派上用场的技巧和窍门。

使用 git stash 命令的实用指南

Ramakrishna Pattnaik 解释了 git stash 命令 的功能。这篇文章重点介绍 git stash 如何帮助你列出、检查、保存和恢复更改,以确保切换分支时的无忧体验。它还可以帮助你跟踪在本地无需提交的更改,而同时保持干净的工作目录。

5 个让你的 Git 技能更上一层楼的 Git 命令

Seth Kenlon 详细介绍了 五个鲜为人知的 Git 命令,它们可以让你的生活更轻松。开发人员可以使用 git whatchangedgit stashgit worktreegit cherry-pick 等命令来节省时间。

Git cherry-pick 简介

Rajeev Bera 教程将引导你了解 git cherry-pick 命令 是什么,为什么和如何使用它,并列出 git cherry-pick 可以帮助你避免棘手的情况所有用例。

3 个使用 git cherry-pick 命令的原因

我分享了 利用 git cherry-pick 如何帮助你避免冗余,一次性处理多个提交并恢复丢失的更改。

使用 git worktree 自由地尝试你的代码

git stash 命令负责将更改保存到工作目录。Seth Kenlon 向我们介绍了 git worktree 和几个 git worktree 用例,它们可以帮助你将存储库恢复到已知状态。

Git 上下文切换的 4 个技巧

Olaf Alders 的这篇文章讨论了使用 Git 时 切换分支的四种不同方式 的利弊。这些选项将帮助你简化工作流程,并保持干净的工作目录,而不会丢失你的更改。

查找 Git 提交中的更改

Seth Kenlon 解释了如何利用如 git log 和 git whatchanged 等简单命令来提取有关 Git 提交内容中更改的特定信息。这是一个有用的快捷方式,而且名字很容易记住。

管理主目录的 7 个 Git 技巧

Seth Kenlon 分享了 使用 Git 管理和组织 $HOME 变量 的注意事项,并解释了它如何让他的跨设备生活更实用。更好的是,这让他可以自由地尝试新想法,因为他知道他可以轻松地将它们回滚。

GitOps 与 DevOps:有什么区别?

Bryant Son 向你介绍了 GitOps,他将其描述为 DevOps 的进化版本,它使用 Git 作为单一事实来源。这篇文章还列出了其它有用资源,可用于学习 DevOps 并在开源领域找到工作。

开始使用 Argo CD

Ayush Sharma 详细介绍了 Argo CD 的优势,这是一种基于拉取式的 GitOps 开发工具。Argo CD 通过在 Git 中管理 Kubernetes 清单并将它们同步到集群中,为你提供两全其美的体验。

你能想到其他让你的生活更轻松的 Git 技巧吗?请在评论中告诉我们。


via: https://opensource.com/article/22/1/git-tutorials

作者:Manaswini Das 选题:lujun9972 译者:stevenzdg988 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

“遴选”可以解决 Git 仓库中的很多问题。以下是用 git cherry-pick 修复错误的三种方法。

 title=

在版本控制系统中摸索前进是一件很棘手的事情。对于一个新手来说,这可能是非常难以应付的,但熟悉版本控制系统(如 Git)的术语和基础知识是开始为开源贡献的第一步。

熟悉 Git 也能帮助你在开源之路上走出困境。Git 功能强大,让你感觉自己在掌控之中 —— 没有哪一种方法会让你无法恢复到工作版本。

这里有一个例子可以帮助你理解“ 遴选 cherry-pick ”的重要性。假设你已经在一个分支上做了好几个提交,但你意识到这是个错误的分支!你现在该怎么办?你现在要做什么?要么在正确的分支上重复所有的变更,然后重新提交,要么把这个分支合并到正确的分支上。等一下,前者太过繁琐,而你可能不想做后者。那么,还有没有办法呢?有的,Git 已经为你准备好了。这就是“遴选”的作用。顾名思义,你可以用它从一个分支中手工遴选一个提交,然后转移到另一个分支。

使用遴选的原因有很多。以下是其中的三个原因。

避免重复性工作

如果你可以直接将相同的提交复制到另一个分支,就没有必要在不同的分支中重做相同的变更。请注意,遴选出来的提交会在另一个分支中创建带有新哈希的新提交,所以如果你看到不同的提交哈希,请不要感到困惑。

如果您想知道什么是提交的哈希,以及它是如何生成的,这里有一个说明可以帮助你。提交哈希是用 SHA-1 算法生成的字符串。SHA-1 算法接收一个输入,然后输出一个唯一的 40 个字符的哈希值。如果你使用的是 POSIX 系统,请尝试在您的终端上运行这个命令:

$ echo -n "commit" | openssl sha1

这将输出一个唯一的 40 个字符的哈希值 4015b57a143aec5156fd1444a017a32137a3fd0f。这个哈希代表了字符串 commit

Git 在提交时生成的 SHA-1 哈希值不仅仅代表一个字符串。它代表的是:

sha1(
    meta data
        commit message
        committer
        commit date
        author
        authoring date
    Hash of the entire tree object
)

这就解释了为什么你对代码所做的任何细微改动都会得到一个独特的提交哈希值。哪怕是一个微小的改动都会被发现。这是因为 Git 具有完整性。

撤销/恢复丢失的更改

当你想恢复到工作版本时,遴选就很方便。当多个开发人员在同一个代码库上工作时,很可能会丢失更改,最新的版本会被转移到一个陈旧的或非工作版本上。这时,遴选提交到工作版本就可以成为救星。

它是如何工作的?

假设有两个分支:feature1feature2,你想把 feature1 中的提交应用到 feature2

feature1 分支上,运行 git log 命令,复制你想遴选的提交哈希值。你可以看到一系列类似于下面代码示例的提交。commit 后面的字母数字代码就是你需要复制的提交哈希。为了方便起见,您可以选择复制前六个字符(本例中为 966cf3)。

commit 966cf3d08b09a2da3f2f58c0818baa37184c9778 (HEAD -> master)
Author: manaswinidas <[email protected]>
Date:   Mon Mar 8 09:20:21 2021 +1300

   add instructions

然后切换到 feature2 分支,在刚刚从日志中得到的哈希值上运行 git cherry-pick

$ git checkout feature2
$ git cherry-pick 966cf3.

如果该分支不存在,使用 git checkout -b feature2 来创建它。

这里有一个问题。你可能会遇到下面这种情况:

$ git cherry-pick 966cf3
On branch feature2
You are currently cherry-picking commit 966cf3d.

nothing to commit, working tree clean
The previous cherry-pick is now empty, possibly due to conflict resolution.
If you wish to commit it anyway, use:

   git commit --allow-empty

Otherwise, please use 'git reset'

不要惊慌。只要按照建议运行 git commit --allow-empty

$ git commit --allow-empty
[feature2 afb6fcb] add instructions
Date: Mon Mar 8 09:20:21 2021 +1300

这将打开你的默认编辑器,允许你编辑提交信息。如果你没有什么要补充的,可以保存现有的信息。

就这样,你完成了你的第一次遴选。如上所述,如果你在分支 feature2 上运行 git log,你会看到一个不同的提交哈希。下面是一个例子:

commit afb6fcb87083c8f41089cad58deb97a5380cb2c2 (HEAD -&gt; feature2)
Author: manaswinidas &lt;[[email protected]][4]&gt;
Date:   Mon Mar 8 09:20:21 2021 +1300
   add instructions

不要对不同的提交哈希感到困惑。这只是区分 feature1feature2 的提交。

遴选多个提交

但如果你想遴选多个提交的内容呢?你可以使用:

git cherry-pick <commit-hash1> <commit-hash2>... <commit-hashn>

请注意,你不必使用整个提交的哈希值,你可以使用前五到六个字符。

同样,这也是很繁琐的。如果你想遴选的提交是一系列的连续提交呢?这种方法太费劲了。别担心,有一个更简单的方法。

假设你有两个分支:

  • feature1 包括你想复制的提交(从更早的 commitAcommitB)。
  • feature2 是你想把提交从 feature1 转移到的分支。

然后:

  1. 输入 git checkout <feature1>
  2. 获取 commitAcommitB 的哈希值。
  3. 输入 git checkout <branchB>
  4. 输入 git cherry-pick <commitA>^..<commitB> (请注意,这包括 commitAcommitB)。
  5. 如果遇到合并冲突,像往常一样解决,然后输入 git cherry-pick --continue 恢复遴选过程。

重要的遴选选项

以下是 Git 文档 中的一些有用的选项,你可以在 cherry-pick 命令中使用。

  • -e--edit:用这个选项,git cherry-pick 可以让你在提交前编辑提交信息。
  • -s--signoff:在提交信息的结尾添加 Signed-off by 行。更多信息请参见 git-commit(1) 中的 signoff 选项。
  • -S[<keyid>]--pgg-sign[=<keyid>]:这些是 GPG 签名的提交。keyid 参数是可选的,默认为提交者身份;如果指定了,则必须嵌在选项中,不加空格。
  • --ff:如果当前 HEAD 与遴选的提交的父级提交相同,则会对该提交进行快进操作。

下面是除了 --continue 外的一些其他的后继操作子命令:

  • --quit:你可以忘记当前正在进行的操作。这可以用来清除遴选或撤销失败后的后继操作状态。
  • --abort:取消操作并返回到操作序列前状态。

下面是一些关于遴选的例子:

  • git cherry-pick master:应用 master 分支顶端的提交所引入的变更,并创建一个包含该变更的新提交。
  • git cherry-pick master~4 master~2':应用master` 指向的第五个和第三个最新提交所带来的变化,并根据这些变化创建两个新的提交。

感到不知所措?你不需要记住所有的命令。你可以随时在你的终端输入 git cherry-pick --help 查看更多选项或帮助。


via: https://opensource.com/article/21/3/git-cherry-pick

作者:Manaswini Das 选题:lujun9972 译者:wxy 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

使用子模块和子树来帮助你管理多个存储库中共有的子项目。

如果你参与了开源项目的开发,那么你很可能已经用了 Git 来管理你的源码。你可能遇到过有很多依赖和/或子项目的项目。你是如何管理它们的?

对于一个开源组织,要实现社区产品的单一来源文档和依赖管理比较棘手。文档和项目往往会碎片化和变得冗余,这致使它们很难维护。

必要性

假设你想把单个项目作为一个存储库内的子项目,传统的方法是把该项目复制到父存储库中,但是,如果你想要在多个父项目中使用同一个子项目呢?如果把子项目复制到所有父项目中,当有更新时,你都要在每个父项目中做修改,这是不太可行的。这会导致父项目中的冗余和数据不一致,使更新和维护子项目变得很困难。

Git 子模块和子树

如果你可以用一条命令把一个项目放进另一个项目中,会怎样呢?如果你随时可以把一个项目作为子项目添加到任意数目的项目中,并可以同步更新修改呢?Git 提供了这类问题的解决方案:Git 子模块 submodule 和 Git 子树 subtree 。创建这些工具的目的是以更加模块化的水平来支持共用代码的开发工作流,旨在 Git 存储库 源码管理 source-code management (SCM)与它下面的子树之间架起一座桥梁。

 title=

生长在桑树上的樱桃树

下面是本文要详细介绍的概念的一个真实应用场景。如果你已经很熟悉树形结构,这个模型看起来是下面这样:

 title=

Git 子模块是什么?

Git 在它默认的包中提供了子模块,子模块可以把 Git 存储库嵌入到其他存储库中。确切地说,Git 子模块指向子树中的某次提交。下面是我 Docs-test GitHub 存储库中的 Git 子模块的样子:

 title=

文件夹@提交 Id 格式表明这个存储库是一个子模块,你可以直接点击文件夹进入该子树。名为 .gitmodules 的配置文件包含所有子模块存储库的详细信息。我的存储库的 .gitmodules 文件如下:

 title=

你可以用下面的命令在你的存储库中使用 Git 子模块:

克隆一个存储库并加载子模块

克隆一个含有子模块的存储库:

$ git clone --recursive <URL to Git repo>

如果你之前已经克隆了存储库,现在想加载它的子模块:

$ git submodule update --init

如果有嵌套的子模块:

$ git submodule update --init --recursive

下载子模块

串行地连续下载多个子模块是很枯燥的工作,所以 clonesubmodule update 会支持 --jobs (或 -j)参数:

例如,想一次下载 8 个子模块,使用:

$ git submodule update --init --recursive -j 8
$ git clone --recursive --jobs 8 <URL to Git repo>

拉取子模块

在运行或构建父项目之前,你需要确保依赖的子项目都是最新的。

拉取子模块的所有修改:

$ git submodule update --remote

使用子模块创建存储库:

向一个父存储库添加子树:

$ git submodule add <URL to Git repo>

初始化一个已存在的 Git 子模块:

$ git submodule init

你也可以通过为 submodule update 命令添加 --update 参数在子模块中创建分支和追踪提交:

$ git submodule update --remote

更新子模块的提交

上面提到过,一个子模块就是一个指向子树中某次提交的链接。如果你想更新子模块的提交,不要担心。你不需要显式地指定最新的提交。你只需要使用通用的 submodule update 命令:

$ git submodule update

就像你平时创建父存储库和把父存储库推送到 GitHub 那样添加和提交就可以了。

从一个父存储库中删除一个子模块

仅仅手动删除一个子项目文件夹不会从父项目中移除这个子项目。想要删除名为 childmodule 的子模块,使用:

$ git rm -f childmodule

虽然 Git 子模块看起来很容易上手,但是对于初学者来说,有一定的使用门槛。

Git 子树是什么?

Git 子树 subtree ,是在 Git 1.7.11 引入的,让你可以把任何存储库的副本作为子目录嵌入另一个存储库中。它是 Git 项目可以注入和管理项目依赖的几种方法之一。它在常规的提交中保存了外部依赖信息。Git 子树提供了整洁的集成点,因此很容易复原它们。

如果你参考 GitHub 提供的子树教程来使用子树,那么无论你什么时候添加子树,在本地都不会看到 .gittrees 配置文件。这让我们很难分辨哪个是子树,因为它们看起来很像普通的文件夹,但是它们却是子树的副本。默认的 Git 包中不提供带 .gittrees 配置文件的 Git 子树版本,因此如果你想要带 .gittrees 配置文件的 git-subtree 命令,必须从 Git 源码存储库的 /contrib/subtree 文件夹 下载 git-subtree。

你可以像克隆其他常规的存储库那样克隆任何含有子树的存储库,但由于在父存储库中有整个子树的副本,因此克隆过程可能会持续很长时间。

你可以用下面的命令在你的存储库中使用 Git 子树。

向父存储库中添加一个子树

想要向父存储库中添加一个子树,首先你需要执行 remote add,之后执行 subtree add 命令:

$ git remote add remote-name <URL to Git repo>
$ git subtree add --prefix=folder/ remote-name <URL to Git repo> subtree-branchname

上面的命令会把整个子项目的提交历史合并到父存储库。

向子树推送修改以及从子树拉取修改

$ git subtree push-all

或者

$ git subtree pull-all

你应该使用哪个?

任何工具都有优缺点。下面是一些可能会帮助你决定哪种最适合你的特性:

  • Git 子模块的存储库占用空间更小,因为它们只是指向子项目的某次提交的链接,而 Git 子树保存了整个子项目及其提交历史。
  • Git 子模块需要在服务器中可访问,但子树是去中心化的。
  • Git 子模块大量用于基于组件的开发,而 Git 子树多用于基于系统的开发。

Git 子树并不是 Git 子模块的直接可替代项。有明确的说明来指导我们该使用哪种。如果有一个归属于你的外部存储库,使用场景是向它回推代码,那么就使用 Git 子模块,因为推送代码更容易。如果你有第三方代码,且不会向它推送代码,那么使用 Git 子树,因为拉取代码更容易。

自己尝试使用 Git 子树和子模块,然后在评论中留下你的使用感想。


via: https://opensource.com/article/20/5/git-submodules-subtrees

作者:Manaswini Das 选题:lujun9972 译者:lxbwolf 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出