Perforce 用户的 Git

发布于 2024-09-17 19:33:06 字数 3137 浏览 5 评论 0 原文

我使用 Perforce 已有很多年了。我想改用 git 来编写我的个人代码,但我见过的所有 git 教程要么假设您是一个完整的源代码控制 n00b(这使得它们非常乏味),要么假设您习惯于svn(我不是)。

我知道 p4,而且我也了解分布式源代码控制系统背后的想法(所以我不需要推销,谢谢)。我想要的是从 p4 命令到等效 git 命令的转换表,以及没有 p4 等效命令的“不能没有”命令。

由于我怀疑每个 p4 用户都使用 p4 的不同子集,因此以下是我经常在 p4 中执行的一些操作,我希望能够在 git 中执行这些操作,这些操作从我查看的文档中并不是显而易见的:

  1. 在单个客户端中创建多个待定更改列表。 (p4 change)
  2. 编辑待处理的变更列表。 (也p4更改
  3. 查看我的所有待处理更改列表的列表(p4更改-s待定
  4. 我的客户端中所有已更改文件的列表(p4打开)或在待定更改列表(p4描述)中
  5. 查看待定更改列表的差异(我为此使用一个包装器脚本,该脚本使用p4 diff和< ,
  6. 对于给定文件,查看哪些提交的更改列表影响了给定文件的哪些行 (p4 annotate)
  7. 查看影响该文件的更改列表的描述列表(p4 log)
  8. 提交待处理的更改列表 (p4 Submit -c)
  9. 中止待处理的更改列表 (p4 revert)

其中很多都围绕“变更列表”。 “变更列表”是 p4 术语。 git 的等效术语是什么?

听起来分支可能是 git 用户用来代替 p4 所谓的变更列​​表的东西。有点令人困惑,因为 p4 也有一个叫做分支的东西,尽管它们似乎只是模糊相关的概念。 (虽然我一直认为 p4 的分支概念非常奇怪,但它又与经典的 RCS 分支概念不同。)

无论如何......我不确定如何使用 git 的分支来完成我通常在 p4 变更列表中所做的事情。在 p4 中我可以做这样的事情:

$ p4 edit a.txt
$ p4 change a.txt
Change 12345 created.

此时我有一个包含 a.txt 的 changlist。我可以编辑描述并继续工作,而无需提交更改列表。另外,如果事实证明我需要对其他一些文件进行一些更改,例如代码的其他层中的错误修复,我可以在同一个客户端中执行此操作:

$ p4 edit z.txt
$ p4 change z.txt
Change 12346 created.

现在我在同一个客户端中有两个单独的更改列表。我可以同时处理这些工作,并且不需要做任何事情来“切换”它们。当需要提交时,我可以单独提交它们:

$ p4 submit -c 12346  # this will submit the changes to z.txt
$ p4 submit -c 12345  # this will submit the changes to a.txt

我不知道如何在 git 中复制它。根据我的实验,git add 似乎没有与当前分支关联。据我所知,当我 git commit 时,无论我当时在哪个分支,它都会提交我 git add 的所有文件

$ git init
Initialized empty Git repository in /home/laurence/git-playground/.git/
$ ls
a.txt  w.txt  z.txt
$ git add -A .
$ git commit
 Initial commit.
 3 files changed, 3 insertions(+), 0 deletions(-)
 create mode 100644 a.txt
 create mode 100644 w.txt
 create mode 100644 z.txt
$ vi a.txt z.txt 
2 files to edit
$ git status
# On branch master
# Changed but not updated:
#   (use "git add <file>..." to update what will be committed)
#   (use "git checkout -- <file>..." to discard changes in working directory)
#
#   modified:   a.txt
#   modified:   z.txt
#
no changes added to commit (use "git add" and/or "git commit -a")
$ git branch aardvark
$ git checkout aardvark
M   a.txt
M   z.txt
Switched to branch 'aardvark'
$ git add a.txt 
$ git checkout master
M   a.txt
M   z.txt
Switched to branch 'master'
$ git branch zebra
$ git checkout zebra
M   a.txt
M   z.txt
Switched to branch 'zebra'
$ git add z.txt 
$ git status
# On branch zebra
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#   modified:   a.txt
#   modified:   z.txt
#
$ git checkout aardvark
M   a.txt
M   z.txt
Switched to branch 'aardvark'
$ git status
# On branch aardvark
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#   modified:   a.txt
#   modified:   z.txt

:例如,aardvark 和 zebra 分支似乎包含完全相同的一组更改,并且根据 git status 的输出,似乎在任一分支中进行提交都会产生相同的效果。我做错了什么吗?

I've been using Perforce for a number of years. I'd like to switch to using git for my personal code, but all of the git tutorials that I've seen either assume that you'e a complete source control n00b (which makes them incredibly tedious) or that you're used to svn (which I'm not).

I know p4, and I also understand the idea behind a distributed source control system (so I don't need a sales pitch, thanks). What I'd like is a translation table from p4 command to equivalent git commands, as well as the "can't live without" commands that have no p4 equivalent.

Since I suspect every p4 user uses a different subset of p4, here are some of the things I regularly do in p4 that I'd like to be able to do in git that aren't immediately obvious from the docs I've looked at:

  1. create multiple pending changelists in a single client. (p4 change)
  2. edit a pending changelist. (also p4 change)
  3. see a list of all of my pending changelists (p4 changes -s pending)
  4. list of all of the changed files in my client (p4 opened) or in a pending changelist (p4 describe)
  5. see a diff of a pending changelist (I use a wrapper script for this which uses p4 diff and p4 describe)
  6. for a given file, see which submitted changelists affected which lines (p4 annotate)
  7. for a given file, see a list of the descriptions of the changelists that affected the file (p4 log)
  8. submit a pending changelist (p4 submit -c)
  9. abort a pending changelist (p4 revert)

A lot of these revolve around "changelists". "changelist" is p4 terminology. What's the git equivalent term?

It sounds like branches might be what git users use in place of what p4 calls changelists. A bit confusing, since p4 also has something called a branch though they seem to be only vaguely related concepts. (Though I always thought p4's concept of a branch was pretty weird it is different yet again from the classic RCS concept of a branch.)

Anyway... I'm not sure how to accomplish what I normally do in p4 changelists with git's branches. In p4 I can do something like this:

$ p4 edit a.txt
$ p4 change a.txt
Change 12345 created.

At this point I have a changlist that contains a.txt. I can edit the description and continue working without submitting the changelist. Also, if it turns out that I need to make some changes to some other files, like say a bugfix in some other layer of the code, I can do that in the same client:

$ p4 edit z.txt
$ p4 change z.txt
Change 12346 created.

Now I have two separate changelists in the same client. I can work on these concurrently, and I don't need to do anything to "switch between" them. When it comes time to commit, I can submit them separately:

$ p4 submit -c 12346  # this will submit the changes to z.txt
$ p4 submit -c 12345  # this will submit the changes to a.txt

I can't figure out how to replicate this in git. From my experiments, it doesn't appear that git add is associated with the current branch. As far as I can tell, when I git commit it's going to commit all files that I git add-ed no matter what branch I was in at the time:

$ git init
Initialized empty Git repository in /home/laurence/git-playground/.git/
$ ls
a.txt  w.txt  z.txt
$ git add -A .
$ git commit
 Initial commit.
 3 files changed, 3 insertions(+), 0 deletions(-)
 create mode 100644 a.txt
 create mode 100644 w.txt
 create mode 100644 z.txt
$ vi a.txt z.txt 
2 files to edit
$ git status
# On branch master
# Changed but not updated:
#   (use "git add <file>..." to update what will be committed)
#   (use "git checkout -- <file>..." to discard changes in working directory)
#
#   modified:   a.txt
#   modified:   z.txt
#
no changes added to commit (use "git add" and/or "git commit -a")
$ git branch aardvark
$ git checkout aardvark
M   a.txt
M   z.txt
Switched to branch 'aardvark'
$ git add a.txt 
$ git checkout master
M   a.txt
M   z.txt
Switched to branch 'master'
$ git branch zebra
$ git checkout zebra
M   a.txt
M   z.txt
Switched to branch 'zebra'
$ git add z.txt 
$ git status
# On branch zebra
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#   modified:   a.txt
#   modified:   z.txt
#
$ git checkout aardvark
M   a.txt
M   z.txt
Switched to branch 'aardvark'
$ git status
# On branch aardvark
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#   modified:   a.txt
#   modified:   z.txt

In this example, the aardvark and zebra branches seem to contain exactly the same set of changes, and based on the output of git status it appears that doing a commit in either will have the same effect. Am I doing something wrong?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

要走干脆点 2024-09-24 19:33:07

我和你一样因为缺乏“变更列表”概念而苦恼,它与 git 分支并不完全相同。

我将编写一个小脚本,该脚本将创建一个更改列表文件,其中包含该更改列表中的文件列表。

另一个命令只需调用 git commit -a @change_list_contents.txt 然后“git commit”即可提交某个更改列表

希望有帮助,
埃利亚斯

I suffer like you with the lack of the "changelist" concept which is not exactly the same as git branches.

I would write a small script that will create a changelist file with the list of files in that changelist.

Another command to submit just a certain changelist by simply calling git commit -a @change_list_contents.txt and then "git commit"

Hope that helps,
Elias

情绪 2024-09-24 19:33:07

是来自未来的我。

现在我已经使用 git 多年了,我认为它可能会很有趣
看看我会如何回答以前的自己这个问题。

具体答案如下,但总体主题是:在 git 中,功能分支
承担 perforce 变更列表的角色
。但在很多方面,它们更加灵活
这种灵活性意味着您经常需要多打字,并且有
犯错误的方式也更多。

Perforce 中的分支往往是长期的、重量级的东西。你不做
经常分支。然而,在 git 中,分支很便宜。在git中,分支是
只不过是一个指向提交的指针。在git中,有些分支是长期的,
就像《Perforce》中的那些。一个常见的例子是main(或master)。

然而,通常的做法是制作短暂的专题(或主题)
分支机构。这些分支机构通常保持“私有”状态,而不是
“待处理的更改列表”,您有这些分支之一。您可以添加提交,
删除提交、重新排序提交以及将提交压缩在一起。您还可以
更改分支“附加”到“目标”分支的位置。这大部分是
使用 git rebase -i 完成,这看起来像是一个可怕的命令,但实际上是
非常容易使用,而且功能非常强大。

记得刚开始学习git的时候,有重写历史的想法
对我来说这似乎是一个糟糕的主意。然而,其他版本控制系统
(包括被迫)也这样做,只是他们不承认而已。为了
例如,如果您的 p4 客户端有更改,并且您“同步”,它会推送您的
在新同步的更改“之后”被拉下的更改。这正是
与变基相同!

无论如何,以下是上述具体“我该怎么办”问题的答案:

在单个客户端中创建多个挂起的更改列表。 (p4更改)

使用单独的功能/主题分支,一个用于您正在处理的每件事。

编辑待处理的变更列表。 (也p4更改)

我主要使用 git rebase -i 来实现此目的。

查看我所有待处理更改列表的列表(p4 更改 -s 待处理)

使用 gitbranch 列出本地分支。这还将列出以下分支
不是您的功能分支,因此您可能需要采用命名约定
将您的功能分支分开。

我的客户端(p4 打开)或待处理的所有已更改文件的列表
更改列表(p4 描述)

您可以使用 git status 来查看未提交的更改。

您可以使用 git diff --name-only 来查看哪些文件在不同版本之间发生了更改。
特定的提交和另一个提交或您的工作树。例如,如果您
想要查看当前分支和分支 main 之间发生了什么变化:

git diff --name-only main

查看待定变更列表的差异(我为此使用了一个包装脚本
使用 p4 diff 和 p4 描述)

使用不带 --name-only 选项的 git diff 。您还可以使用 git difftool 或 git 中未包含的其他 git diffing 工具。我用
git multidiffvim-multidiff

对于给定文件,查看哪些提交的更改列表影响了哪些行 (p4
注释)

这可以通过 gitblame 来完成。

对于给定文件,请参阅更改列表的描述列表
影响文件(p4日志)

在文件上使用 git log 可以做到这一点。

提交待处理的变更列表(p4 提交 -c)

纯粹在 git 中,这可以通过 git merge 来完成。例如:

git switch main
git merge feature-branch

我更喜欢进行“半线性”合并,这意味着我将执行两个步骤:

git switch feature-branch
git rebase main

git switch main
git merge --no-ff feature-branch

尽管如果我的功能分支上只有一个提交,我只会快进
合并。

然而,当与一个拥有 Github 或 GitLab 等 git 主机的团队合作时,我
几乎从不使用 git merge。相反,我会提交一个
拉取请求/合并请求,然后(代码审查后)使用 Web UI 合并
git 主机的。

在 GitLab 上,我创建合并请求的方式是将我的功能分支推送到
一些额外的推送选项。我有一个 shell 脚本,git-mr,它简化了这个过程。
重要的部分是:

BRANCH_NAME=$(git symbolic-ref --short HEAD)
git push \
    -o merge_request.create \
    -o merge_request.remove_source_branch \
    -u origin "$BRANCH_NAME:$BRANCH_NAME"

中止待处理的变更列表(p4 恢复)

要删除功能分支:

git branch -D feature-branch

It's me from the future.

Now that I've been using git for many years, I thought it might be interesting
to see how I'd answer this question from my former self.

Specific answers are below, but the overarching theme is: in git, feature branches
take on the role of perforce's changelists
. In many ways, they are more flexible, though
that flexibility means you often need to do a bit more typing, and there are
also more ways to make a mistake.

Branches in Perforce tend to be long-term, heavyweight things. You don't make
branches very often. In git, however, branches are cheap. In git, a branch is
little more than a pointer to a commit. In git, some branches are long-term,
like those in Perforce. A common example is main (or master).

However, it's common practice to also make short-lived feature (or topic)
branches. These branches usually remain "private", and instead of having
"pending changelists", you have one of these branches. You can add commits,
remove commits, reorder commits, and squash commits together. You can also
change where the branch is "attached" to the "target" branch. Most of this is
done with git rebase -i, which seems like a scary command, but is actually
pretty easy to use, and is very powerful.

I remember when I first started learning git, the idea of rewriting history
seemed like a terrible idea to me. However, other version control systems
(including perforce) do this as well, they just don't acknowledge it. For
example, if you have changes in your p4 client, and you "sync", it'll push your
changes "after" the newly synced changes that got pulled down. This is exactly
the same as a rebase!

Anyway, here are answers to the specific "How do I" questions above:

create multiple pending changelists in a single client. (p4 change)

Use separate feature/topic branches, one for each thing you're working on.

edit a pending changelist. (also p4 change)

I primarily use git rebase -i for this.

see a list of all of my pending changelists (p4 changes -s pending)

Use git branch to list local branches. This will also list branches that
aren't your feature branches, so you may want to adopt a naming convention to
set your feature branches apart.

list of all of the changed files in my client (p4 opened) or in a pending
changelist (p4 describe)

You can use git status to see uncommited changes.

You can use git diff --name-only to see which files have changed between a
particular commit and another commit or your working tree. For example, if you
want to see what changed between your current branch and the branch main:

git diff --name-only main

see a diff of a pending changelist (I use a wrapper script for this which
uses p4 diff and p4 describe)

Use git diff without the --name-only option. You can also use git difftool, or other git diffing tools that aren't iincluded with git. I use
git multidiff with vim-multidiff.

for a given file, see which submitted changelists affected which lines (p4
annotate)

This can be done with git blame.

for a given file, see a list of the descriptions of the changelists that
affected the file (p4 log)

Using git log on a file does this.

submit a pending changelist (p4 submit -c)

Purely in git, this would be done with git merge. For example:

git switch main
git merge feature-branch

I prefer to do a "semi-linear" merge, meaning I'll do two steps:

git switch feature-branch
git rebase main

git switch main
git merge --no-ff feature-branch

Though if there's only one commit on my feature branch, I'll just fast-forward
merge.

However, when working with a team with a git host like Github or GitLab, I
pretty much never use git merge. Instead, I'll submit a
pull-request/merge-request, and then (after code review) merge using the web UI
of the git host.

On GitLab, the way I create a merge request is to push my feature branch with
some extra push options. I have a shell script, git-mr which simplifies this.
The important part is:

BRANCH_NAME=$(git symbolic-ref --short HEAD)
git push \
    -o merge_request.create \
    -o merge_request.remove_source_branch \
    -u origin "$BRANCH_NAME:$BRANCH_NAME"

abort a pending changelist (p4 revert)

To delete a feature branch:

git branch -D feature-branch
对风讲故事 2024-09-24 19:33:07

我没有足够的 p4 经验来制作实际的备忘单,但至少有一些相似之处可以依靠。 p4“变更集”是 git“提交”。

对本地工作空间的更改将通过 git add 添加到“索引”中,随后使用 git commit 提交索引。因此,无论出于何种意图和目的,索引都是您待定的变更列表。

您可以使用 git diff 和 git status 来查看更改,其中 git diff 通常显示工作区和索引之间的更改,但是 git diff --cached 显示索引和存储库之间的更改(= 您的待处理更改列表)。

如需更深入的信息,我推荐 http://progit.org/book/。由于您通常了解版本控制,因此您可能可以浏览很多内容并提取特定于 git 的信息......

I don't have enough p4 experience to produce an actual cheat sheet, but there are at least some similarities to fall back on. A p4 "changeset" is a git "commit".

Changes to your local work space get added to the "index" with git add, and the index later gets committed with git commit. So the index is your pending changelist, for all intents and purposes.

You look at changes with git diff and git status, where git diff usually shows changes between the workspace and the index, but git diff --cached shows changes between the index and the repository (= your pending changelist).

For more in depth information, I recommend http://progit.org/book/. Since you know version control in general, you can probably skim a lot of it and extract the git-specific information...

彼岸花似海 2024-09-24 19:33:07

git 中有一个更轻量级的替代方案,可以成为您工作流程的一部分;使用 git 暂存区。

我经常只是进行更改,然后作为多次提交提交(例如添加调试语句、重构、实际修复错误)。您可以先进行更改,然后选择如何提交它们(可以选择使用 git 暂存区域),而不是设置强制更改列表,然后进行更改,然后提交。

您可以使用以下命令从命令行提交特定文件:

git commit a.txt
git commit z.txt

或者首先显式暂存文件:

git add a.txt
git commit
git add z.txt
git commit

git gui 将允许您从文件中选择行或块以在暂存区域中构建提交。如果您希望在不同的提交中对一个文件进行更改,那么这一点非常有用。从 git 迁移到 perforce 后,这是我真正怀念的一件事。

对于此工作流程,需要记住一个小警告。如果您对文件进行更改 A 和 B,测试该文件,然后提交 A,那么您还没有测试该提交(独立于 B)。

There is a more lightweight alternative in git that could form part of your workflow; using the git staging area.

I often just make changes then submit as several commits (e.g. add debug statements, refactor, actually fix a bug). Rather than setting up your perforce changelists, then make changes, then submit, you can just make your changes then choose how to submit them (optionally using the git staging area).

You can commit particular files from the command line with:

git commit a.txt
git commit z.txt

Or explicitly staging the files first:

git add a.txt
git commit
git add z.txt
git commit

git gui will let you select lines or hunks from within files to build up a commit in the staging area. This is very useful if you have changes in one file that you want to be in different commits. Having moved from git to perforce and this is one thing that I really miss.

There is a small caveat to bear in mind with this workflow. If you make changes A and B to a file, test the file, then commit A then you haven't tested that commit (independently of B).

挽你眉间 2024-09-24 19:33:07

这并没有具体回答您的问题,但我不知道您是否知道 2 个用户、5 个工作区版本的 perforce 可以从 perforce 网站

这样,如果您愿意,您可以在家里使用 perforce 来完成您的个人项目。唯一令人烦恼的是 5 个工作空间,这可能有点限制,但能够强制用于家庭使用,这真是令人难以置信。

This doesn't answer your question specifically, but I don't know if you are aware that a 2 User, 5 Workspace version of perforce is free to download and use from the perforce website.

This way you can use perforce at home for your personal projects if you wish. The one annoyance is the 5 workspaces which can be a bit limiting, but its pretty incredible to have perforce available for home use.

太傻旳人生 2024-09-24 19:33:07

在相当广泛地使用 Perforce 和 git 后,我​​发现只有一种方法可以使用 git 接近 Perforce 变更列表。

首先要理解的是,要在 git 中以不完整的方式正确实现此功能,例如尝试将其硬塞到分支中,需要进行以下更改:git 需要为单个分支提供多个暂存区域。

Perforce 变更列表允许实现 git 中没有的等效工作流程。考虑以下工作流程:

Check out a branch
Modify file A and add it to changelist 1
Modify file B and add it to changelist 2

如果您尝试使用 git 中的分支来执行此操作,您将得到两个分支,其中一个分支对文件 A 进行了更改,另一个分支对文件 进行了更改>B,但没有地方可以同时看到文件 AB 的更改。

我能看到的最接近的近似方法是使用 git add 。 -p,然后使用 'a''d' 子命令选择或拒绝整个文件。然而,这并不完全相同,这里的差异源于两个系统的一般操作方式的根本差异。

Git(和颠覆,这对本次讨论来说并不重要)允许更改文件,而无需提前告知任何人。你只需更改一个文件,然后在提交更改时让 git 整理所有内容。 Perforce 要求您在允许更改之前主动检出文件,因此更改列表必须存在。本质上,Perforce 要求您在更改文件之前将其添加到索引中。因此,Perforce 中需要多个变更列表,也是 git 没有等效项的原因。 它根本不需要它们。

Having used both Perforce and git fairly extensively, there's only one way I can see to get anywhere near Perforce changelists with git.

The first thing to understand is that to correctly implement this functionality in git in such a way that it's a not a complete kluge, e.g. trying to shoehorn it into branches, would require the following change: git would require multiple staging areas for a single branch.

Perforce changelists permit a workflow that simply has no equivalent in git. Consider the following workflow:

Check out a branch
Modify file A and add it to changelist 1
Modify file B and add it to changelist 2

If you try to do this using branches in git you'll wind up with two branches, one of which has the changes to file A, the other has the changes to file B, but no place where you can see the changes to both files A and B at the same time.

The closest approximation I can see is to use git add . -p and then use the 'a' and 'd' sub-commands to select or reject entire files. However that's not quite the same, and the difference here stems from a fundamental disparity in the general modus operandi of the two systems.

Git (and subversion, not that it matters for this discussion) allow a file to be changed without telling anyone about this ahead of time. You just change a file, and then let git sort it all out when you commit the changes. Perforce requires you to actively check out a file before changes are allowed, and it is for this reason that changelists have to exist. In essence, Perforce requires you to add a file to the index before changing it. Hence the necessity for multiple changelists in Perforce, and also the reason why git has no equivalent. It simply doesn't need them.

还不是爱你 2024-09-24 19:33:07

在 Git 2.27(2020 年第 2 季度)中,“git p4” 学习了四个新钩子以及“--no-verify”选项来绕过它们(以及现有的“ >p4-预提交”钩子)。

请参阅 提交 1ec4a0a提交 38ecf75, 提交cd1e0dc(2020 年 2 月 14 日),以及提交 4935c45提交aa8b766提交 9f59ca4, 提交 6b602a2(2020 年 2 月 11 日)作者:Ben Keene (seraphire)
(由 Junio C Hamano -- gitster -- 合并于 提交 5f2ec21,2020 年 4 月 22 日)

git-p4:添加p4提交挂钩

签字人:本·基恩

git 命令“commit”支持许多支持更改提交命令行为的挂钩。

git-p4.py 程序只有一个现有钩子“p4-pre-submit”。

此命令发生在进程的早期。

流程中没有用于以编程方式修改 P4 更改列表文本的挂钩。

git-p4.py 添加 3 个新挂钩到提交选项。

新的钩子是:

  • p4-prepare-changelist - 在创建更改列表文件后执行此挂钩。
    即使设置了 --prepare-p4-only 选项,该钩子也会被执行。
    此挂钩忽略 --no-verify 选项,以与 git 提交

  • p4-changelist - 在用户编辑更改列表后执行此挂钩。
    如果用户选择了 --prepare-p4-only 选项,则不要执行此挂钩。
    该钩子将遵守 --no-verify,遵循 的约定git 提交

  • p4-post-changelist - 在 P4 提交过程成功完成后执行此挂钩。
    该钩子不带任何参数,并且无论 --no-verify 选项如何,都会执行。

不会检查其返回值。

对新挂钩的调用:p4-prepare-changelistp4-changelistp4-post-changelist 都应该是在 try-finally 块内调用。


在 Git 2.28(2020 年第 3 季度)之前,“--prepare-p4-only”选项应该在重播一个变更集后停止,但会继续运行(错误地?)

请参阅 提交 2dfdd70(2020 年 5 月 12 日),作者:本·基恩(seraphire
(由 Junio C Hamano -- gitster -- 合并于 提交 7a8fec9,2020 年 6 月 2 日)

git-p4.py:修复< code>--prepare-p4-only 多次提交时出错

签字人:本·基恩

当使用 git p4 Submit--prepare-p4-only 选项时,程序应该准备一个 p4 更改列表并通知用户有更多提交正在等待处理然后停止处理。

p4-changelist 挂钩功能引入了一个错误,导致程序继续尝试同时处理所有待处理的更改列表。

当应用提交成功并且程序应该继续时,函数applyCommit返回True
但是,当设置了可选标志 --prepare-p4-only 时,程序应在第一个应用程序后停止。

更改 P4Submit 的 run 方法中的逻辑,以在成功完成 applyCommit 方法后检查标志 --prepare-p4-only

如果超过 1 个提交正在等待提交到 P4,该方法将正确准备 P4 更改列表,但它仍会以退出代码 1 退出应用程序。

当前文档没有定义在这种情况下退出代码应该是什么。

With Git 2.27 (Q2 2020), "git p4" learned four new hooks and also "--no-verify" option to bypass them (and the existing "p4-pre-submit" hook).

See commit 1ec4a0a, commit 38ecf75, commit cd1e0dc (14 Feb 2020), and commit 4935c45, commit aa8b766, commit 9f59ca4, commit 6b602a2 (11 Feb 2020) by Ben Keene (seraphire).
(Merged by Junio C Hamano -- gitster -- in commit 5f2ec21, 22 Apr 2020)

git-p4: add p4 submit hooks

Signed-off-by: Ben Keene

The git command "commit" supports a number of hooks that support changing the behavior of the commit command.

The git-p4.py program only has one existing hook, "p4-pre-submit".

This command occurs early in the process.

There are no hooks in the process flow for modifying the P4 changelist text programmatically.

Adds 3 new hooks to git-p4.py to the submit option.

The new hooks are:

  • p4-prepare-changelist - Execute this hook after the changelist file has been created.
    The hook will be executed even if the --prepare-p4-only option is set.
    This hook ignores the --no-verify option in keeping with the existing behavior of git commit.

  • p4-changelist - Execute this hook after the user has edited the changelist.
    Do not execute this hook if the user has selected the --prepare-p4-only option.
    This hook will honor the --no-verify, following the conventions of git commit.

  • p4-post-changelist - Execute this hook after the P4 submission process has completed successfully.
    This hook takes no parameters and is executed regardless of the --no-verify option.

It's return value will not be checked.

The calls to the new hooks: p4-prepare-changelist, p4-changelist, and p4-post-changelist should all be called inside the try-finally block.


Before Git 2.28 (Q3 2020), the "--prepare-p4-only" option is supposed to stop after replaying one changeset, but kept going (by mistake?)

See commit 2dfdd70 (12 May 2020) by Ben Keene (seraphire).
(Merged by Junio C Hamano -- gitster -- in commit 7a8fec9, 02 Jun 2020)

git-p4.py: fix --prepare-p4-only error with multiple commits

Signed-off-by: Ben Keene

When using git p4 submit with the --prepare-p4-only option, the program should prepare a single p4 changelist and notify the user that more commits are pending and then stop processing.

A bug has been introduced by the p4-changelist hook feature that causes the program to continue to try and process all pending changelists at the same time.

The function applyCommit returns True when applying the commit was successful and the program should continue.
However, when the optional flag --prepare-p4-only is set, the program should stop after the first application.

Change the logic in the run method for P4Submit to check for the flag --prepare-p4-only after successfully completing the applyCommit method.

If more than 1 commit is pending submission to P4, the method will properly prepare the P4 changelist, however it will still exit the application with an exitcode of 1.

The current documentation does not define what the exit code should be in this condition.

脱离于你 2024-09-24 19:33:06

我没有太多使用 perforce,所以这可能不完全是 1:1 的翻译。然后,像 git 和 Mercurial 这样的分布式源代码控制系统无论如何都有不同的工作流程,所以确实没有(也不应该)有 1:1 的翻译。无论如何,这里是:

  • 创建多个挂起的变更列表 ->请改用分支。在 git 中,分支轻且快速,创建时间不到一秒,合并通常不到两秒。不要害怕经常分支和变基。

    git 分支新分支名称
    git checkout 新分支名称
    

    或者在一行中完成所有操作:

    git checkout -b 新分支名称
    
  • 查看所有待处理更改列表的列表 ->由于多个挂起的变更列表相当于多个分支,只需查看分支即可:

    git 分支
    

    如果您还想查看远程分支:

    git 分支 -a
    

    在成功合并后立即删除分支被认为是一种很好的做法,这样您就不必跟踪哪些分支正在等待合并以及哪些分支已经被合并。

  • 列出所有已更改的文件 ->对于特定分支中的单个挂起的“更改列表”,git 有索引或缓存的概念。为了提交更改,您必须首先将文件添加到该索引。这允许您手动选择哪组文件代表单个更改或忽略不相关的文件。要查看添加或不添加到此索引的文件的状态,只需执行以下操作:

    git 状态
    
  • 查看待处理更改列表的差异 ->这有两个部分。首先查看工作目录和索引之间的差异:

    <前><代码>git diff

    但是,如果您想知道现在输入的内容与上次提交之间的差异,那么您实际上是在要求工作目录+索引与 HEAD 之间的差异:

    git diff HEAD
    
  • 对于给定的文件,查看哪些提交的更改列表影响了哪些行 ->这很简单:

    git Blame 文件名
    

    如果您处于窗口环境中,甚至更好:

    git gui 责任文件名
    

    Git gui 需要更长的时间来解析文件(它是用 tcl 而不是 C 编写的),但它有很多简洁的功能,包括通过单击提交 ID 来“时间旅行”回到过去的能力。我只希望他们能够实现“时间旅行”到未来的功能,这样我就可以找出给定的错误最终将如何解决;-)

  • 对于给定的文件,请参阅更改列表的描述列表影响文件的 ->也很简单:

    git 日志文件名
    

    但是 git log 是一个比这个更强大的工具。事实上,我的大部分个人脚本都搭载 git log 来读取存储库。阅读手册页。

  • 提交待处理的变更列表 ->也很简单:

    git 提交
    

请参阅我对上一个问题的回答,了解我典型的 git 工作流程: 学习 Git。需要知道我是否走在正确的轨道上

如果您遵循我概述的工作流程,那么您会发现像 gitk 这样的工具更有价值,因为它可以让您清楚地看到更改组。


附加答案:

Git 非常灵活,有多种方法可以完成您所描述的操作。要记住的是始终为您正在开发的每个功能启动一个新分支。这意味着主分支不会受到影响,因此您可以随时返回到它来修复错误。在 git 中工作几乎总是从以下开始:

git checkout -b new-feature-a

现在您可以编辑文件 a.txt。要同时处理另一个功能,请执行以下操作:

git checkout master
git checkout -b new-feature-z

现在您可以编辑文件 z.txt。要切换回 a.txt:

git checkout new-feature-a

但是等等,new-feature-z 发生了变化,并且 git 不允许你切换分支。此时你有两个选择。第一个是最简单的,将所有更改提交到当前分支:

git add .
git commit
git checkout new-feature-a

这是我的建议。但如果你确实还没有准备好提交代码,你可以暂时隐藏它:

git stash

现在你可以切换到分支 new-feature-a。要返回到您正在处理的代码,只需弹出存储:

git checkout new-feature-z
git stash pop

当所有完成后,将所有更改合并回主控:

git merge --no-ff new-feature-a
git merge --no-ff new-feature-z

因为合并是如此快速和简单(简单是因为冲突非常罕见,并且冲突解决,当发生冲突时,而不是太难了)我们在 git 中使用分支来做所有事情。

这是 git 中分支的常见用法的另一个示例,您在其他源代码控制工具(可能除了 Mercurial)中看不到它:

需要不断更改配置文件以反映您的开发环境吗?然后使用分支:

git checkout -b dev-config

现在在您最喜欢的编辑器中编辑您的配置文件,然后提交更改:

git add .
git commit

现在每个新分支都可以从 dev-config 分支而不是 master 开始:

git checkout dev-config
git checkout -b new-feature-branch

完成后,从 new-feature 中删除 dev-config 中的编辑- 使用交互式变基分支:

git rebase -i master

删除不需要的提交然后保存。现在您有了一个干净的分支,无需进行自定义配置编辑。是时候合并回 master 了:

git checkout master
git merge --no-ff new-feature-branch
# because master have changed, it's a good idea to rebase dev-config:
git checkout dev-config
git rebase master

应该注意的是,当所有更改都发生在同一个文件中时,使用 git rebase -i 删除编辑甚至可以工作。 Git 会记住更改,而不是文件内容*。

*注意:实际上,技术上并不完全正确,但作为用户,这就是感觉


更多附加答案:

因此,从您的评论来看,您似乎希望有两个分支同时存在,以便您可以测试组合代码如何工作。嗯,这是说明分支的强大功能和灵活性的好方法。

首先,谈谈廉价分支和可修改历史记录对工作流程的影响。当我使用 CVS 和 SVN 时,我总是有点不愿意承诺。这是因为提交不稳定的代码将不可避免地搞乱其他人的工作代码。但有了 git,我就不再害怕了。那是因为在 git 中,在我将它们合并到 master 之前,其他人不会得到我的更改。所以现在我发现自己每编写 5 行就提交一次代码。你不需要完美的远见来做出承诺。你只需要改变你的心态:commit-to-branch==add-to-changeset,merge-to-master==commit-changeset。

那么,回到例子。我就是这样做的。假设您有一个分支 new-feature-z 并且您想使用 new-feature-a 测试它。我只想创建一个新分支来测试它:

# assume we are currently in branch new-feature-z
# branch off this branch for testing
git checkout -b feature-z-and-feature-a
# now temporarily merge new-feature-a
git merge --no-ff new-feature-a

现在您可以测试了。如果您需要修改某些内容以使功能 z 与功能 a 一起使用,请这样做。如果是这样,您可以将更改合并回相关分支。使用 git rebase -i 删除合并中不相关的更改。

或者,您也可以使用 git rebase 临时更改 new-feature-z 的基数以指向 new-feature-a:

# assume we are currently in branch new-feature-z
git rebase new-feature-a

现在分支历史记录已修改,以便 new-feature-z 将基于 new-feature-a而不是主人。现在你可以测试了。在此分支中提交的任何更改都将属于分支 new-feature-z。如果您需要修改 new-feature-a,只需切换回它并变基即可获取新更改:

git checkout new-feature-a
# edit code, add, commit etc..
git checkout new-feature-z
git rebase new-feature-a
# now new-feature-z will contain new changes from new-feature-a

完成后,只需变基回 master 以删除 new-feature-a 中的更改:

# assume we are currently in branch new-feature-z
git rebase master

不要害怕开始一个新的分支。不要害怕创建一个一次性分支。不要害怕扔掉树枝。由于 merge==submit 和 commit==add-to-changeset 不要害怕经常提交。请记住,提交是开发人员的终极撤消工具。

哦,还有一件事,在 git 中删除的分支仍然存在于你的存储库中。因此,如果您不小心删除了后来意识到有用的内容,您始终可以通过搜索历史记录将其恢复。所以不要害怕扔掉树枝。

I haven't used perforce much so this may not be exactly be a 1:1 translation. Then again distributed source control systems like git and mercurial have a different workflow anyway so there really isn't (and there shouldn't) be a 1:1 translation. Anyway, here goes:

  • Create multiple pending changelists -> Use branches instead. In git branches are light and quick, takes less than a second to create and typically less than two seconds to merge. Don't be afraid of branching and rebase often.

    git branch new-branch-name
    git checkout new-branch-name
    

    Or do it all in one line:

    git checkout -b new-branch-name
    
  • See a list of all pending changelists -> Since the equivalent of multiple pending changelist is multiple branches just view the branches:

    git branch
    

    If you want to view remote branches as well:

    git branch -a
    

    It is considered good practice to immediately delete a branch after a successful merge so you don't have to keep track of which branch are pending to be merged and which have already been merged.

  • List all changed files -> For a single pending "changelist" in a specific branch git has a concept of the index or cache. In order to commit a change you must first add files to this index. This allows you to manually select which group of files represent a single change or to ignore irrelevant files. To see the status of which files are added, or not to this index just do:

    git status
    
  • See a diff of a pending changelist -> There are two parts to this. First to see a diff between the working directory and the index:

    git diff
    

    But if you want to know the diff between what you're typing now and the last commit then you are really asking for a diff between the working directory+index and the HEAD:

    git diff HEAD
    
  • For a given file, see which submitted changelists affected which lines -> This is easy:

    git blame filename
    

    or even better, if you are in a windowing environment:

    git gui blame filename
    

    Git gui takes longer to parse the file (it was written in tcl instead of C) but it has lots of neat features including the ability to "time travel" back into the past by clicking on a commit ID. I only wish they'd implement a feature to "time travel" to the future so I can find out how a given bug will finally be resolved ;-)

  • For a given file, see a list of the descriptions of the changelists that affected the file -> also easy:

    git log filename
    

    But git log is a much more powerful tool than just this. In fact most of my personal scripts piggyback off-of git log to read the repository. Read the man page.

  • Submit a pending changelist -> Also easy:

    git commit
    

See my answer to a previous question to see my typical git workflow: Learning Git. Need to know if I am on the right track

If you follow the workflow I outlined then you'll find tools like gitk to be much more valuable since it allows you to clearly see groups of changes.


Additional answer:

Git is very flexible and there are several ways to do what you describe. The thing to remember is to always start a new branch for each feature you're working on. This means the master branch isn't touched so you can always go back to it to do bug fixes. Working in git one should almost always start with:

git checkout -b new-feature-a

Now you can edit file a.txt. To work concurrently on another feature do:

git checkout master
git checkout -b new-feature-z

Now you can edit file z.txt. To switch back to a.txt:

git checkout new-feature-a

But wait, there are changes to new-feature-z and git won't let you switch branches. At this point you have two choices. The first is the simplest, commit all changes to the current branch:

git add .
git commit
git checkout new-feature-a

This is what I'd recommend. But if you are really not ready to commit the code, you can temporarily stash it:

git stash

Now you can switch to branch new-feature-a. To go back to the code you were working on just pop the stash:

git checkout new-feature-z
git stash pop

When all is done merge back all changes to master:

git merge --no-ff new-feature-a
git merge --no-ff new-feature-z

Because merges are so quick and easy (easy because conflicts are so rare and conflict resolution, when one does happen, not too hard) we use branches in git for everything.

Here's another example of a common use of branches in git that you don't see in other source control tools (except perhaps mercurial):

Need to keep changing your config files to reflect your dev environment? Then use a branch:

git checkout -b dev-config

Now edit your config files in your favourite editor then commit changes:

git add .
git commit

Now every new branch can start from the dev-config branch instead of master:

git checkout dev-config
git checkout -b new-feature-branch

Once you're done remove the edits in dev-config from new-feature-branch using interactive rebase:

git rebase -i master

Delete the commits you don't want then save. Now you have a clean branch without custom config edits. Time to merge back to master:

git checkout master
git merge --no-ff new-feature-branch
# because master have changed, it's a good idea to rebase dev-config:
git checkout dev-config
git rebase master

It should be noted that removing edits with git rebase -i even works when all changes happen in the same file. Git remembers changes, not file content*.

*note: actually, technically not entirely true but as a user that's what it feels like


More additional answer:

So, from you comments it looks like you want to have two branches to exist simultaneously so you can test how the combined code works. Well, this is a good way to illustrate the power and flexibility of branches.

First, a word on the implication of cheap branching and modifiable history on your workflow. When I was using CVS and SVN I was always a bit reluctant to commit. That's because committing unstable code would inevitably f**k up other people's working code. But with git I lost that fear. That's because in git other people won't get my changes until I merge them to master. So now I find myself committing code every 5 lines I write. You don't need perfect foresight to commit. You just need to change your mindset: commit-to-branch==add-to-changeset, merge-to-master==commit-changeset.

So, back to examples. Here's how I would do it. Say you have a branch new-feature-z and you want to test it with new-feature-a. I would just create a new branch to test it:

# assume we are currently in branch new-feature-z
# branch off this branch for testing
git checkout -b feature-z-and-feature-a
# now temporarily merge new-feature-a
git merge --no-ff new-feature-a

Now you can test. If you need to modify something to make feature-z work with feature-a then do so. If so you can merge back the changes to the relevant branch. Use git rebase -i to remove irrelevant changes from the merge.

Alternatively, you can also use git rebase to temporarily change the base of new-feature-z to point to new-feature-a:

# assume we are currently in branch new-feature-z
git rebase new-feature-a

Now the branch history is modified so that new-feature-z will be based off new-feature-a instead of master. Now you can test. Any changes committed in this branch will belong to the branch new-feature-z. If you need to modify new-feature-a just switch back to it and the rebase to get the new changes:

git checkout new-feature-a
# edit code, add, commit etc..
git checkout new-feature-z
git rebase new-feature-a
# now new-feature-z will contain new changes from new-feature-a

When you're done, simply rebase back to master to remove changes from new-feature-a:

# assume we are currently in branch new-feature-z
git rebase master

Don't be afraid to start a new branch. Don't be afraid to start a throwaway branch. Don't be afraid to throw away branches. And since merge==submit and commit==add-to-changeset don't be afraid to commit often. Remember, commit is a developer's ultimate undo tool.

Oh, and another thing, in git deleted branches still exist in your repository. So if you've accidentally deleted something that you later realise is useful after all you can always get it back by searching the history. So don't be afraid to throw away branches.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文