Git

在Matomo,我们使用Git版本控制系统。下面是一些使用git的技巧,以及如何在命令行上使用git的指南。

如果你更喜欢通过你的IDE使用Git,比如PHPStorm,或者如果你更习惯于使用稍微不同的命令或方法,那么请使用你觉得舒服的首选选项。通常没有对与错,做事情也没有一种方法。

先决条件

克隆存储库

Github支持通过HTTPS和SSH url进行克隆。例如,在克隆存储库时,您总是希望使用SSH urlgit@github.com: matomo-org / matomo.git

要克隆一个存储库,请使用以下示例:

Git克隆git@github.com:matomo-org/matomo. Git matomo Git子模块更新——init Git LFS pull——exclude=

这将把Matomo存储库克隆为matomo目录,初始化所有子模块,并使用LFS提取所有截图测试文件。

创建一个新分支

在开始编写新特性之前,应该确保将更改与主分支分开。这允许你稍后从该分支创建一个拉请求,然后可以对其进行检查

我们要给我们的新分公司起个名字。分支名称理想情况下总是包含GitHub问题编号。matomo - 1111或者如果这是一个Jira的问题,那么。dev - 1111.如果需要,还可以将描述性名称添加到分支名称中。但这并不是必需的,因为分支只是暂时存在,相关的问题将包含所有所需的详细信息。理想情况下,分支名不只是一个纯粹的数字,因为它可能会与提交散列发生冲突(下面会解释这是什么),git不知道它是应该签出分支还是提交。使用实例添加分支。

git checkout -b错误修复$MAIN_BRANCH

哪里需要更换MAIN_BRANCH美元与当前的主要分支。这是一个例子* .x-dev在Matomo on - premise工作时亚博账号每天2000元出租(5. x-dev是撰写本文时的主要分支)。对于Matomo的WordPress来说,这将是开发.例如:Git checkout -b错误修复5.x-dev.的分支中创建一个新的分支5. x-dev分支。否则,如果您没有指定基本分支,并且您已经在另一个具有更改的分支中,那么它将从当前分支中将所有更改复制到新分支中。

结帐命令将创建一个新的分支- b选项,否则它将尝试加载现有的分支。

而不是Git checkout -b你也可以使用Git开关-c如果您正在使用更新版本的git。

添加、提交和推送代码

在添加或修改了一些文件之后,您将希望将这些更改推送到远程存储库。即使一个特性还没有完成,定期提交和推送(至少每天)也是很好的,这样如果由于某种原因丢失了更改,您总是有备份。

添加文件

首先要执行git状态查看哪些文件已被修改。

要查看您在这些文件中更改了什么,可以执行该命令git diff.如果您只想查看特定文件或目录的更改,那么您可以将多个文件或目录作为参数列出,如Git diff file1 file2 dir1

一旦您对更改感到满意git diff向你展示,你可以添加这些文件,这样它们就可以被提交和推送。到目前为止,这些文件是“非阶段性的”,一旦你添加文件,那么这些将是“阶段性的”。任何添加的文件都将包含在下次提交中。

添加文件和目录的命令类似于git diff这意味着你可以添加多个文件和目录路径来定义哪些应该被添加:

Git添加index.php lang-directory file2

您不必一次添加所有文件。你可以在提交之前将它们添加到多个注释中:

添加lang-directory file2

在某些情况下,你可能更喜欢下面的命令,它会交互式地询问你想要添加或不添加哪些更改:

Git添加-p #请注意,这将不适用于二进制文件,如图像,这些将被跳过

你不应该执行这样的命令Git add—all要添加所有文件,因为您可能会添加一些不想添加的文件。

验证更改

在我们进入提交这些添加的更改的下一步之前,您需要首先验证您添加了哪些更改。要做到这一点,运行命令:

Git diff——缓存

撤消已添加的(暂存的)文件

如果你注意到你添加了一个你不打算添加的更改,那么你可以在提交之前通过执行下面的命令再次撤销它:

git reset HEAD file2 dir1 dir2 #一次性取消多个文件和目录

提交更改

一旦添加了这些更改(“阶段性”),您就可以提交这些更改了。你可以执行以下命令:

git commit -m 'My awesome commit message'

方法更新提交消息——修改选择:

git commit - modify -m 'My awesome commit message'

在Matomo中,提交消息不太重要,因为我们通常创建一个拉请求,然后在合并PR时将所有的提交压缩成一个提交。拉请求的标题将成为提交消息。如果你已经推送了一个提交,那么就不要再更新提交消息了,因为它并不重要,在最坏的情况下会导致问题,因为你需要强制推送。

当您进行提交时,这些提交还没有发送到任何远程服务器。在实际将这些文件推送到远程服务器之前,您可以执行一次或多次提交,我们将进入下一步。

提交散列

每个提交都有一个唯一的哈希来标识这个提交(也称为提交引用)。

例如提交2 b0891d1efb016882cd807196741963e3f6437b1

这些散列在很多方面都很有用

  • 你可以使用例如查看这个提交的内容。显示$COMMIT_HASH
  • 您可以使用它来检出这个提交,类似于一个分支git checkout $COMMIT_HASH
  • 还有更多。

一些git操作可能需要这样的提交散列。你可以在很多地方找到这些历史,比如Github提交历史或执行历史git日志

检查上次提交

如果您提交了更改,并希望看到上次提交是什么样子,那么您可以执行git显示

在不丢失更改的情况下撤消尚未推送的最后一次提交

如果您提交了不想提交的内容,这可能很有用。该命令将撤消上次提交,但保留更改。

git重置-软头~1

从技术上讲,您还可以撤销已经推送的最后一个提交,但它将需要强制推送(见下文)。

推动改变

可以使用该命令进行推送git推.如果您正在处理一个分支,那么您可能需要定义所谓的“远程”的名称(通常是起源)和你想要推送的分支的名称。例如,如果您创建了一个分支myfeature然后你需要执行Git push origin myfeature

推送意味着它将把之前的所有提交发送到远程服务器,也就是github.com。然后,您将看到分支出现在GitHub用户界面中,Travis将自动运行我们的自动化测试套件。

当你访问你在github.com上推送更改的存储库时,GitHub会显示你推送到的分支,你可以再次检查推送的更改。然后,如果你对这些改变感到满意,或者寻求反馈,你就会做出更多的努力创建一个拉请求

力推动

大多数主要的分支都受到保护,不受改写历史的力量推动。如果你需要重写历史记录(这应该很少需要),那么你会想使用下面的命令:

Git push—force-with-lease

Git push—force它也覆盖了整个远程分支与你的本地分支,——force-with-lease是更安全的,因为它可以确保您不会覆盖其他人的工作,因为它会检查您的本地原始副本是否与远程原始副本相同,并防止推送,如果其他人同时推送到分支。

我们的各种git存储库都使用子模块。从git的角度来看,存储库中的子模块类似于作为文件处理,但其内容包括特定的提交散列。这样git就知道它引用了子模块中的哪个提交。

子模块配置在.gitmodules文件(请看这个例子),其内容如下:

[子模块"plugins/SecurityInfo"] path = plugins/SecurityInfo url = git@github.com:matomo-org/plugin-SecurityInfo.git

这意味着存储库在路径中有一个子模块插件/并且它指向存储库git@github.com: matomo-org / plugin-SecurityInfo.git.如果该子模块的内容包括提交散列0 c3c4182d96edcb23c896ca86042bab06247db42,然后是目录插件/并且将检出此特定提交的内容。

每次这个提交哈希值改变时,你都需要执行Git子模块更新以确保路径签出了子模块的正确版本。

注意:如果你想知道为什么我们在GitHub上的存储库使用HTTPS git url,这是为了让Travis可以克隆这个存储库而没有问题。

在子模块中进行更改并更新对该子模块的引用

更新子模块的流程通常如下所示,其中我们假设有一个存储库,我们将其称为“父”,其中有一个子模块插件/ SecurityInfo.在replace命令中MAIN_BRANCH美元与主分支的分支名称和MY_FEATURE_BRANCH美元你的特征分支的名称。

  • cd插件/ SecurityInfo
  • mynewbranch $MAIN_BRANCH
  • 在子模块中做一些更改。
  • 您可以像这样在存储库中添加、提交和推送更改git add Controller.php && git commit -m "Update" && git push origin mynewbranch
  • 这个提交将获得一个新的唯一的提交散列。

接下来的步骤取决于您是否需要立即在“Parent”存储库中进行这些更改。

变体A——你不需要将父库中的子模块更改作为你的特性的一部分

大多数时候都是这样。当您向子模块添加新特性或修复错误时,就会发生这种情况。然后在子模块中创建PR并合并此更改。一旦子模块中的PR被合并,那么您将更新“Parent”存储库中的引用,以确保更改将包含在下一个版本中,并且在“Parent”存储库的测试中考虑该更改。

  • 在子模块的存储库中创建一个拉取请求。
  • 将此更改合并到主分支中。
  • 现在PR已经合并到子模块中,你想要在“Parent”存储库中将子模块的引用更新为最新的提交散列:
    • git checkout -b $MY_FEATURE_BRANCH $MAIN_BRANCH
    • cd插件/ SecurityInfo
    • git检查$MAIN_BRANCH
    • git拉原点$MAIN_BRANCH
    • cd . . / . .
    • git添加插件/SecurityInfo这将执行子模块引用更改
    • git commit -m更新子模块
    • git push origin $MY_FEATURE_BRANCH

现在您可以在“Parent”存储库中创建一个拉请求来更新子模块引用。

变体B—您需要将子模块更改作为您的特性的一部分

当您在“Parent”存储库中进行一些重构时,需要在子模块中进行更改以保证不中断时,这是最需要的。它通常表示突破性的变化。例如,你在Matomo核心中改变了一个现有的方法,它需要改变插件。

  • git添加插件/SecurityInfo
  • git commit -m更新子模块
  • git push origin $MY_FEATURE_BRANCH

现在,“Parent”存储库将子模块指向分支中的提交mynewbranch我们在子模块中创建的。现在,您将完成“Parent”存储库中的工作,然后为子模块和主存储库创建一个拉取请求。您需要先合并子模块中的PR,然后按照“变体A”中的步骤进行操作。

修复“引用不是树”的错误

当您忘记推送子模块时

假设在子模块中做了一些更改。然后你提交这些更改,但你忘记像下面这样推送更改:

  • cd插件/ SecurityInfo
  • git checkout -b $MY_FEATURE_BRANCH $MAIN_BRANCH
  • git add Controller.php && git commit -m "Update"
  • 这里通常会有推,但你忘了。
  • cd . . / . .
  • git添加插件/SecurityInfo这将执行子模块引用更改
  • git commit -m更新子模块
  • git推

当你现在推送时,子模块的更新将不会工作,因为提交只存在于你的本地计算机上,但从未推送过。要解决这个问题,你需要使用这些命令来推动提交:

  • cd插件/ SecurityInfo
  • git push origin $MY_FEATURE_BRANCH

当分支被删除时

如果将子模块指向同时已删除分支的分支中的提交,则可能会发生相同的错误。要修复此问题,您需要将子模块中的引用更新为仍然存在的提交。下面的示例将提交引用更新回主分支中的最新提交。

  • cd插件/ SecurityInfo
  • git检查$MAIN_BRANCH
  • git拉原点$MAIN_BRANCH
  • cd . . / . .
  • git添加插件/SecurityInfo
  • git commit -m更新子模块
  • git推

修复错误“致命的:远程错误:上传包:不是我们的参考”

造成此错误的确切原因目前尚不清楚,但可能与合并失败有关。它可能伴随着各种“警告:…”为子模块找到多个配置。xxx的消息。

要解决这个问题:

  • 保存分支变更的补丁:
  • git diff $MAIN_BRANCH $FEATURE_BRANCH > $FEATURE_BRANCH.patch
  • 关闭PR而不合并。
  • 结账主要分支:
  • git检查$MAIN_BRANCH
  • 从主分支创建一个新分支:
  • git checkout -b $FEATURE_BRANCH_NEW
  • 应用补丁:
  • git应用$FEATURE_BRANCH.patch
  • 提交并推送更改:
  • git commit -m 'New branch'
  • git推
  • 从新的分支创建一个新的PR。

意外提交子模块?

你是否在Matomo或其他项目上做了一些工作,不小心覆盖了子模块提交?下面的命令可以帮助您将子模块指向与主分支相同的提交。

替换如下命令中的变量:

  • MAIN_BRANCH美元带有主分支的名称。有时这是生活开发* .x-dev(如。5. x-dev).
  • FEATURE_BRANCH美元你犯了错误的分支机构的名称。
  • SUBMODULE_DIR美元要更正的子模块的路径。例如“插件/Morpheus/图标”。
git checkout $MAIN_BRANCH #切换到主分支git子模块更新——init——递归git checkout $FEATURE_BRANCH git checkout $MAIN_BRANCH $SUBMODULE_DIR git add $SUBMODULE_DIR #将子模块添加回原来的状态git commit -m '恢复git子模块' #提交更改

其他有用的命令

将主分支中的最新更改合并到功能分支中

你可能在你的分支上工作了几个小时或几天,与此同时,你希望在你的功能分支中有一些主分支中的变化。例如,这可能有助于解决合并冲突,或者如果在主分支中某些测试已修复,但在您的分支中失败。要做到这一点,请按照以下步骤进行替换MAIN_BRANCH美元使用您正在使用的存储库的主分支名称(例如5. x-dev)和取代MY_FEATURE_BRANCH美元您目前工作的分支机构的名称。

git checkout $MAIN_BRANCH git pull origin $MAIN_BRANCH git checkout $MY_FEATURE_BRANCH git merge $MAIN_BRANCH #然后保存文件。假设你没有任何非分阶段的变化,你也可以做' git rebase $MAIN_BRANCH ' git push origin $MY_FEATURE_BRANCH

检查一个特定的Matomo版本

命令可以检出Matomo的特定版本git checkout命令连同版本号一起使用。例如:

Git checkout 4.4.0

修复在你的特性分支中意外推送其他提交的问题

假设您在一个名为喷火然后,您开始在一个名为酒吧.你执行Git checkout -b bar而不是git checkout -b bar $MAIN_BRANCH.这意味着分支酒吧也将包括所有的变化喷火当你创建pull request时,会包含来自另一个PR的更改,并且不清楚你添加了哪些更改作为分支工作的一部分酒吧

有很多方法可以解决这个问题。

如果在创建的PR中有很小的变化

这可能只在一个文件中只有很少的更改时有用:

  • 关闭PR而不合并。
  • 从主分支创建一个新分支。
  • 再次手动应用相同的更改。
  • 创建一个新的PR。

最简单的解决方案

如果分支中只有很少的提交酒吧然后,最简单的解决方案是创建一个新分支,并选择您想要提交到这个新分支中的所有提交。然后在不合并的情况下关闭最初创建的PR,并创建一个新的PR。

git checkout -b $MY_FEATURE_BRANCH $MAIN_BRANCH git cherry-pick $COMMIT_SHA #将$COMMIT_SHA替换为你想要保留的提交哈希值git cherry-pick $COMMIT_SHA #如果需要,你可能需要樱桃选择多个提交git push origin $MY_FEATURE_BRANCH

更复杂的解决方案

更复杂的解决方案可能是找到更改之前的最后一次提交,然后执行git rebase -i $COMMIT_SHA

这允许您删除不想要的提交,只需删除行,然后保存文件。它将改写历史,你需要强行推动这些改变。请注意,如果您在这里做错了一些事情,您的更改可能会丢失,所以要明智地使用它。

日志的变化

您可以记录已经发生的所有更改,以查看在何时由谁执行更改了什么Git log -p

如果您不想获得实际的更改,而只想获得提交消息及其每个引用,则执行git日志

我如何修复错误“一些截图没有存储在LFS”?

错误可能是这样的:

1) Piwik\Tests\Integration\ReleaseCheckListTest::test_screenshotsStoredInLfs一些截图没有存储在LFS: plugins/YourPluginName/ Tests /UI/ expectedscreenshots /Filename.png声明数组为空失败。

您可以使用以下步骤修复此问题:

  • cd插件/ YourPluginName
  • git rm测试/UI/期望截图/*.png
  • 添加测试/UI/期望截图/*.png filter=lfs diff=lfs merge=lfs到文件.gitattributes在你的插件中
  • Git添加了tests .gitattributes
  • git commit -m '删除截图'
  • 再次添加预期的UI测试文件
  • Git添加测试
  • git commit -m '使用LFS添加截图'
  • 然后更新core中的子模块
Baidu