Skip to content

git url: support CSV form (also support verifying a tag with a commit hash) #5903

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 2 commits into from

Conversation

AkihiroSuda
Copy link
Member

@AkihiroSuda AkihiroSuda commented Apr 10, 2025

Commit 1: git url: support CSV form

CSV parameters can be now specified after "##" in a git URL. e.g.,

https://github.com/user/repo.git##ref=v1.0.0,subdir=/dir

Fix #4905, but the syntax differs from the original proposal.

The documents will be added in
https://github.com/docker/docs/blob/main/content/manuals/build/concepts/context.md#url-fragments

Commit 2: git url: support specifying ref and commit together

Fix #5871

}
if isHTTPSourceV {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(Use git show --ignore-all-space to review)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@jedevc
Copy link
Member

jedevc commented Apr 10, 2025

🤔 Wondering why we use the fragment here actually. Wouldn't query parameters make more sense, since there's actually a way of having multiple params there?

So instead:

https://github.com/user/repo.git?tag=mytag&branch=main&commit=cafebab&subdir=/dir

It just feels a bit odd to overload the ##. But I suppose the format is a little tricky, so urgh, no strong opinions, just an idea.

@AkihiroSuda
Copy link
Member Author

Wondering why we use the fragment here actually. Wouldn't query parameters make more sense, since there's actually a way of having multiple params there?

Query params doesn't seem correct here, as it would be sent to the server as an HTTP GET request

@@ -6,6 +6,7 @@ const AttrAuthHeaderSecret = "git.authheadersecret"
const AttrAuthTokenSecret = "git.authtokensecret"
const AttrKnownSSHHosts = "git.knownsshhosts"
const AttrMountSSHSock = "git.mountsshsock"
const AttrCommitHash = "git.commithash"
Copy link
Member Author

@AkihiroSuda AkihiroSuda Apr 10, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(Bikeshedding: this could be also named AttrGitChecksum to follow AttrHTTPChecksum)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@tonistiigi Which one do you prefer?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AttrGitChecksum

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@AkihiroSuda AkihiroSuda changed the title git url: support CSV form git url: support CSV form (also support verifying a tag with a commit hash) Apr 10, 2025
Copy link
Member

@tonistiigi tonistiigi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should include existing features like keep-git-dir, #4905 (comment) . Also #4974 seems like a simple addition.

What if a branch/tag starts with #?

return nil, errors.New("tag, branch, and commit are exclusive")
}
for _, v := range refs {
res.Ref = v
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what's the benefit of different fields if they still get all squashed into same ref.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated to use a single ref

Copy link
Member

@tonistiigi tonistiigi Apr 30, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can't we have it so that ref is used as is, branch is converted to ref=refs/heads/xxx and tag is converted to ref=refs/tags/xxx, or does that break something?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@AkihiroSuda
Copy link
Member Author

AkihiroSuda commented Apr 12, 2025

I think we should include existing features like keep-git-dir, #4905 (comment) .

Can be another PR?

Also #4974 seems like a simple addition.

Can be another PR? Maybe not as easy as keep-git-dir.

What if a branch/tag starts with #?

https://example.com/repo.git##ref=#foohandles #foo as a valid branch/tag.
Updated the unit tests to cover it.

https://example.com/repo.git##foo will begin to fail, but nobody is likely affected?

CSV parameters can be now specified after "##" in a git URL.
e.g.,
https://github.com/user/repo.git##ref=v1.0.0,subdir=/dir

Fix issue 4905, but the syntax differs from the original proposal.

The documents will be added in
https://github.com/docker/docs/blob/main/content/manuals/build/concepts/context.md#url-fragments

Signed-off-by: Akihiro Suda <[email protected]>
Copy link
Member

@tonistiigi tonistiigi left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤔 Wondering why we use the fragment here actually. Wouldn't query parameters make more sense, since there's actually a way of having multiple params there?

Query params doesn't seem correct here, as it would be sent to the server as an HTTP GET request

In LLB we have different sources llb.Git and llb.HTTP and in Dockerfile we already allow this as https:// is a valid git protocol and we use .git and github.com to make a difference. This could be problematic if query options are sent to Git server on clone but that is already not supported. It does look cleaner to me than ##, and we can still support # by combining them, and we wouldn't break the one person using #abc as a branch name atm.

I guess for SSH style URLs it would look weird and nonstandard?

@tianon @fenollp

@@ -151,6 +151,73 @@ func TestParseURL(t *testing.T) {
Path: "/moby/buildkit",
},
},
{
url: "https://github.com/moby/buildkit##ref=v1.0.0,subdir=/subdir",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could we add some SCP/SSH-style URL testcases.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@@ -635,6 +652,16 @@ func (gs *gitSourceHandler) Snapshot(ctx context.Context, g session.Group) (out
}

git = git.New(gitutil.WithWorkTree(checkoutDir), gitutil.WithGitDir(gitDir))
if gs.src.CommitHash != "" {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this happening after we have already completed the checkout instead of before?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just for verification, as we may potentially have an unexpected code path (in future)

refCommitFullHash = gs.src.Ref
}
if refCommitFullHash != "" {
cacheKey := gs.shaToCacheKey(refCommitFullHash, "")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The ref should be set here if one is present even if we know the full hash.

If first build is from ref=master,commithash= and second build(replay pinned from provenance) is from ref=master,commithash=abcdef then they should generate same cache keys. Ideally we would cover this with a testcase.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@@ -207,6 +209,9 @@ func (gs *gitSourceHandler) shaToCacheKey(sha, ref string) string {
if gs.src.Subdir != "" {
key += ":" + gs.src.Subdir
}
if gs.src.CommitHash != "" {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this needed? Isn't sha already same as CommitHash?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, CommitHash can be a partial hash

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why does that matter, if we already have a complete one.

Same as https://github.com/moby/buildkit/pull/5903/files/076850aeb7720b56683710d8e30b05fbb9352b97#diff-bf1789b0b19c8d6533a10da5e27f0b31da2cdcd37510a787498c3d19a985d470 . Eg. if you build from alpine:latest or alpine:latest@sha256 then if the digest matches then they will generate the same cache key.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Adding a new cache key seems safer to enforce hash verification, as an existing cache might have been populated without verifying the sha with the expected value.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can continue the discussion in

@@ -6,6 +6,7 @@ const AttrAuthHeaderSecret = "git.authheadersecret"
const AttrAuthTokenSecret = "git.authtokensecret"
const AttrKnownSSHHosts = "git.knownsshhosts"
const AttrMountSSHSock = "git.mountsshsock"
const AttrCommitHash = "git.commithash"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AttrGitChecksum

@AkihiroSuda
Copy link
Member Author

In LLB we have different sources llb.Git and llb.HTTP and in Dockerfile we already allow this as https:// is a valid git protocol and we use .git and github.com to make a difference. This could be problematic if query options are sent to Git server on clone but that is already not supported. It does look cleaner to me than ##, and we can still support # by combining them, and we wouldn't break the one person using #abc as a branch name atm.

If we are going to make our URL spec further diverged from RFC XXXX, the https:// schema part has to be changed to something like buildkit-git-https:// ?

@tonistiigi
Copy link
Member

If we are going to make our URL spec further diverged from RFC XXXX, the https:// schema part has to be changed to something like buildkit-git-https:// ?

In Dockerfile, where this is only ambiguous, we already have https://domain/smth.git#ref meaning something completely different than doing a HTTP GET of that URL. From a purely URL parsing standpoint, query parameters are a standard part of URLs, while this ## as an alternative fragment separator really isn't.

@AkihiroSuda
Copy link
Member Author

Maybe we should follow "URL Fragment Text Directives" https://wicg.github.io/scroll-to-text-fragment/#example-9acce0ff ?

https://example.com#:~:text=foo&text=bar&unknownDirective

For BK, it would be

https://github.com/user/repo.git#:~:ref=v1.0.0&subdir=/dir

@thaJeztah
Copy link
Member

Curious; is passing these options in the URL itself a hard requirement? Looking at the related ticket, the motivation behind that request was for the current micro-format to be either ambiguous, or hard to grasp. I think the main reason we used a micro-format in the first place was because Dockerfile instructions (like ADD) had no options other than <src> and <dest>.

With this PR, we're inventing yet-another micro format, but now that the Dockerfile format supports --options, would it be a better approach to use some --option for this? I saw a comment from @tianon on the related ticket that effectively there's already a syntax defined by git itself to specify the reference itself #4905 (comment) (refs/tags/xxx, refs/heads/xxx), and having a --option to our availability allows us to have additional options that are more expressive, e.g.;

  • --git-opts=keep-git,ref=refs/tags/xxx,hash=sha256:xxxx,subdir=/dir

For backward-compatibility, we can probably allow passing ref either through the existing micro-format, or through the ref (not both). We could also add "porcelain" options to those options, e.g. tag=v1.2.3, branch=release/v1.2.3, or (given that git doesn't allow @ in tag-names, could even use tag=v1.2.3@sha256:xxxx as shorthand.

@AkihiroSuda
Copy link
Member Author

--git-opts=keep-git,ref=refs/tags/xxx,hash=sha256:xxxx,subdir=/dir

This syntax probably doesn't allow having a single ARG variable that covers both the ref and the hash?

@thaJeztah
Copy link
Member

This syntax probably doesn't allow having a single ARG variable that covers both the ref and the hash?

Yeah, that's true; do we (can we?) expand fields in the flag? Because I guess that would still allow passing these references, which could be by combining (if you want the hash to be "optional"), e.g.;

ARG GIT_TAG=v0.1.0
ARG GIT_HASH=@sha256:deadbeef
ARG GIT_REF=${GIT_TAG}${GIT_HASH}

FROM scratch
ADD --git-opts=ref=${GIT_REF},path=/dir,keep-git=true,depth=1 https://github.com/user/repo.git /src

The only risk there would be if git would accept a change where tag@hash would become a supported format (but possibly we could augment that depending on the version of git that's used?)

@tonistiigi
Copy link
Member

#:~:

Looks really ugly to me, and not really similar with the intent of "text directives" (not that our current anchor usage is).

With this PR, we're inventing yet-another micro format, but now that the Dockerfile format supports --options, would it be a better approach to use some --option for this?

This isn't just ADD command in Dockerfile. We have Git URLs for remote context on buildx build <URL> (and actions etc), --build-context foo=https://....git. Atm. we have BUILDKIT_CONTEXT_KEEP_GIT_DIR as a build-arg that is a pain to use.

@tonistiigi
Copy link
Member

This syntax probably doesn't allow having a single ARG variable that covers both the ref and the hash?

I guess you mean ARG, that would cover repo URL and the version. I sometimes define separate args for version, URL and combination, so if you are building from a fork then you can just set the fork address.

@AkihiroSuda
Copy link
Member Author

not really similar with the intent of "text directives" (not that our current anchor usage is).

https://wicg.github.io/scroll-to-text-fragment/#example-9acce0ff says "The only directive introduced in this spec is the text directive but others could be added in the future"

https://example.com#:~:text=foo&text=bar&unknownDirective

@thaJeztah
Copy link
Member

This isn't just ADD command in Dockerfile. We have Git URLs for remote context on buildx build (and actions etc), --build-context foo=https://....git. Atm. we have BUILDKIT_CONTEXT_KEEP_GIT_DIR as a build-arg that is a pain to use.

Hm, right, but for the positional arg (docker buildx build <URL>), do we need to support all features? I could imagine that --build-context (already a csv format) could get extra options added for more advanced cases. And (I guess?) in a bakefile we'd have more flexibility w.r.t. adding options?

@tianon
Copy link
Member

tianon commented Apr 30, 2025

One of the patches I maintain downstream in my builds of BuildKit is just to remove the recursive submodule clone that's assumed by passing a URL, which I imagine would be a use case that could be unlocked by a more complex format here.

In other words, I finally have an answer to moby/moby#3463 (comment) and ... "the call's coming from inside the house" -- to be fair though, I only use build-via-URL because it embeds slightly better provenance, and I'm not convinced I want to continue doing so in the future because it has a lot of rough edges. This PR frankly adds more, not less, because now we've got an even more complex micro-format for scripting git init+git fetch+..., and most folks will likely have a CI system doing those steps anyhow, so ADD with a Git URL is probably a more compelling use case here and even there IMO doing the git commands explicitly via RUN (or on the host pre-build) is better/cleaner/more obvious/easier to hack on.

@tonistiigi
Copy link
Member

Hm, right, but for the positional arg (docker buildx build ), do we need to support all features? I could imagine that --build-context (already a csv format) could get extra options added for more advanced cases. And (I guess?) in a bakefile we'd have more flexibility w.r.t. adding options?

It's not like there is any other alternative for these cases and because of the defaults in actions Git context is probably 100x more used than ADD <git>. --build-context is not CSV, it is key-value like --build-arg. I'm not sure what you mean by bake, the context/build-context is string there and you need to define BUILDKIT_CONTEXT_KEEP_GIT_DIR separately under args if you wish to control it.

@thaJeztah
Copy link
Member

It's not like there is any other alternative for these cases and because of the defaults in actions Git context is probably 100x more used than ADD .

Right, but I think with both the bake and build actions, the user doesn't interact with the CLI, but with YAML (the definition for the action). So I would expect the action to be able to transform options set in YAML to whatever format or flags are needed to pass this information to buildx (it could even generate a bake-file based on the options the user passed)

It's a bit hard to describe my thinking; mostly we're trying to overload an already overloaded format. Let me drill down "how did we get here?"

  • docker build only supported a local path (. commonly used) to specify the location of the build context
  • When building from a github repository, this required users to first clone the repository, then build, so feature requests came in "could docker do this for me?"
  • inspired by go get, we added support for docker build github.com/name/repo, where github.com was special cased to be detected as "probably a github repository"
  • but now users wanted to build from a remote context that's not "git", so http(s):// was added, and detection what content was served (a file? or perhaps git over https?)
  • ☝️ the common convenience for all of those was that you could basically copy/paste a URL, and use it for build-context. It was not perfect (some git providers required an explicit .git suffix to disambiguate), but things "mostly worked"

We got on a sliding slope when we added support for branches, tags, directories; because now we started to conflate "URL" with our own features. The format was also complicated, so not as intuitive, because you had to make yourself familiar with the micro-format we defined for this, but the set of features was limited so we could cope (on our side), and it was power-user feature, so we expected investment on the user side to learn how to do this.

But effectively, we painted ourselves in a corner because we wanted to continue to have both "it's a git(hub) URL", AND "we want to add our options on top, but still make it an URL".

I just think that we are stretching the limits (too far) now, because we tied ourselves to that; the microformat is out-growing its original intent. It's no longer intuitive, and bolting more options on top only makes this more so; effectively throwing away the reason we added this in the first place (just copy/paste your repository URL!).

Which is why I wondered if we could not use other (command-line) options to specify these options, instead of trying to bolt-on even more.

If that's not an option, perhaps we should make this explicit; it's not a (git) URL anymore, it's a docker / buildkit argument with options.

And if the argument must be an URL (to disambiguate from it being a local path), perhaps we should define a pseudo-scheme for this, e.g.;

buildkit-remote-source://github.com/hello/world/?keep-git=1&depth=5&whatever=foo

Or

buildkit-remote-source:///?type=git&repo=github.com/hello/world&keep-git=1&depth=5&whatever=foo

With our own scheme, we wouldn't have to be concerned that any (query)parameter included would be considered a parameter for the remote host. It would be ~backward compatible (older buildx versions should tell "unsupported scheme"), and we "own" the URL structure, so could add whatever we want.

older buildx versions should tell "unsupported scheme"

☝️ unfortunately we weren't that bright though, so it looks like we don't invalidate schemes we don't support;

docker build -t foo whatever://github.com/foo/bar
[+] Building 0.0s (0/0)                                                                        docker:desktop-linux
ERROR: unable to prepare context: path "whatever://github.com/foo/bar" not found

@tonistiigi
Copy link
Member

It's a bit hard to describe my thinking; mostly we're trying to overload an already overloaded format.

I don't want to overload. The current PR is introducing new concepts like :: separator and CSV. Or buildkit-remote-source:/// would be something completely new. Otoh we already have logic that https://.. .git URLs are actually converted to git clone and querystring is a completely standards-based format for adding key-value properties to https URLs.

but now users wanted to build from a remote context that's not "git", so http(s):// was added,

I don't think this history is quite correct. Building from remote URLs was supported in 2013, I believe even before the name Dockerfile was settled.

With our own scheme,

I do not understand why we would need a new schema. We already have logic for interpreting certain HTTP URLs as Git URLs. This would not be a new concept.

Building from URLs or using URL dependencies is the only way BuildKit can track dependencies securely and validate them. The more builds we can make directly from URLs rather than local source or RUN git clone, the better. We also need to make sure that these things are easy to use, and for me, that disqualifies custom proto or "scroll-to-text fragment. Eg. I like https://github.com/chainguard-dev/apko/blob/main/docs/apko_file.md#includes format, but because we have use cases that need many options, I think querystring is the easiest way to go from the current https:// URL to a URL with additional options for more advanced cases.

@tonistiigi
Copy link
Member

We are likely cutting v0.22 this week. If we can't come to an agreement about the URL syntax, we should at least try to get the LLB bits in. If people are unsure about the querystring then maybe we can leave add it to labs first.

@AkihiroSuda
Copy link
Member Author

AkihiroSuda commented May 13, 2025

Rather than inventing a new microformat, can we just use a JSON string?

ARG FOO='{"remote":"https://github.com/example/foo.git","commit":"v1.0.0","commitHash":"deadbeef"}'

If we don't like this either, a new microformat can be added later without breaking the compatibility.

@AkihiroSuda AkihiroSuda added this to the v0.22.0 milestone May 13, 2025
@tonistiigi
Copy link
Member

Rather than inventing a new microformat,

How is adding a querystring to a URL adding a new microformat?

@AkihiroSuda
Copy link
Member Author

AkihiroSuda commented May 13, 2025

Rather than inventing a new microformat,

How is adding a querystring to a URL adding a new microformat?

Query strings are expected to be set as a part of HTTP GET request.
If we are going to change our interpretation, an existing reference to https://example.com/foo.git?some-existing-site-specific-query=blah may stop working?

@tonistiigi
Copy link
Member

If we are going to change our interpretation, an existing reference to https://example.com/foo.git?some-existing-site-specific-query=blah may stop working?

This has never worked anyway. If it is HTTP URL then it is not handled by Git (and already works fine). If it is a Git URL then

 => ERROR [2/3] ADD https://github.com/moby/buildkit.git?foo=bar /src/                                                                                                                                                                        1.2s
 => CACHED [1/3] FROM docker.io/library/alpine:latest@sha256:a8560b36e8b8210634f77d9f7f9efd7ffa463e380b75e2e74aff4511df3ef88c                                                                                                                 0.0s
 => => resolve docker.io/library/alpine:latest@sha256:a8560b36e8b8210634f77d9f7f9efd7ffa463e380b75e2e74aff4511df3ef88c                                                                                                                        0.0s
------
 > [2/3] ADD https://github.com/moby/buildkit.git?foo=bar /src/:
1.148 warning: redirecting to https://github.com/moby/buildkit?foo=bar/
1.148 fatal: https://github.com/moby/buildkit?foo=bar/info/refs not valid: is this a git repository?
------
ERROR: failed to solve: failed to load cache key: error fetching default branch for repository https://github.com/moby/buildkit.git?foo=bar: git stderr:
warning: redirecting to https://github.com/moby/buildkit?foo=bar/
fatal: https://github.com/moby/buildkit?foo=bar/info/refs not valid: is this a git repository?

same as

» git clone 'https://github.com/moby/buildkit.git?foo=bar'                                                                                                                                                                                  
Cloning into 'buildkit.git?foo=bar'...
warning: redirecting to https://github.com/moby/buildkit?foo=bar/
fatal: https://github.com/moby/buildkit?foo=bar/info/refs not valid: is this a git repository?

What happens internally is I believe

curl -i "https://github.com/moby/buildkit.git/info/refs?service=git-upload-pack" | xxd -c 32 | less

and obviously

curl -L https://github.com/moby/buildkit.git?foo=bar/info/refs?service=git-upload-pack

would always be invalid.

@crazy-max
Copy link
Member

crazy-max commented May 13, 2025

🤔 Wondering why we use the fragment here actually. Wouldn't query parameters make more sense, since there's actually a way of having multiple params there?

So instead:

https://github.com/user/repo.git?tag=mytag&branch=main&commit=cafebab&subdir=/dir

It just feels a bit odd to overload the ##. But I suppose the format is a little tricky, so urgh, no strong opinions, just an idea.

👍 On using query string to enhance Git context handling. This approach offers a more flexible, self-describing and extensible mechanism while keeping backward compatibility with fragment that can be merged but query param takes precedence.

Build Syntax Suffix Commit Used Build Context Used
myrepo.git refs/heads/<default branch> /
myrepo.git?tag=mytag refs/tags/mytag /
myrepo.git?ref=mybranch refs/heads/mybranch /
myrepo.git?ref=pull/42/head refs/pull/42/head /
myrepo.git?subdir=myfolder refs/heads/<default branch> /myfolder
myrepo.git?ref=master&subdir=myfolder refs/heads/master /myfolder
myrepo.git?tag=mytag&subdir=myfolder refs/tags/mytag /myfolder
myrepo.git?ref=mybranch&subdir=myfolder refs/heads/mybranch /myfolder
myrepo.git?ref=master#:myfolder refs/heads/master /myfolder
myrepo.git?subdir=myfolder#master refs/heads/master /myfolder
myrepo.git?ref=dev#master refs/heads/dev /

@tonistiigi
Copy link
Member

myrepo.git?ref=mytag | refs/tags/mytag

I guess you meant myrepo.git?tag=mytag there

@AkihiroSuda
Copy link
Member Author

AkihiroSuda commented May 15, 2025

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Proposal: csv syntax for git repos LLB Git should allow branch/tag ref together with commit
6 participants