blob: aeda207a5980e922ccb1bc12acb4153caf6b29a9 [file] [log] [blame] [view]
Josip Sokcevic79a4a542023-08-15 00:35:081# Git submodules
2
3A Git submodule is a Git repository inside another Git repository. Chromium
4project doesn't rely on Git submodules directly. Instead, gclient sync is used
5to manage Git dependencies.
6
7In 2023Q3, we started to move source of Git dependencies from DEPS files to Git
8submodules. While we do our best to hide complexities of submodules, some will
9be exposed.
10
Josip Sokcevic00eefc52023-08-27 22:11:2711IMPORTANT NOTE: Due to a bug in fsmonitor, we encourage you to disable it until
12the underlying bug is fixed. More details in https://crbug.com/1475405.
13
Josip Sokcevic79a4a542023-08-15 00:35:0814[TOC]
15
16## A quick introduction to Git submoduldes
17
18[Git submodules](https://git-scm.com/docs/gitsubmodules) are managed via the
19combination of `.gitmodules` files and gitlinks. `.gitmodules` is a text file
20that configures submodules, and each submodule entry contains the path to the
21submodule's worktree and the URL of the submodule. Gitlink is a special type of
22file in the Git database that tracks a submodule commit.
23
Josip Sokcevic703849e2023-08-16 00:13:3424You can find an example of Git dependency below. Note that gclient-condition is
25a custom property used by gclient and not git. It's identical to `condition` in
26`DEPS` and the allowed variables are defined in `vars = {` section of `DEPS`.
Josip Sokcevic79a4a542023-08-15 00:35:0827
28`.gitmodules`:
29
30```
31[submodule "third_party/catapult"]
32 path = third_party/catapult
33 url = https://chromium.googlesource.com/catapult.git
Josip Sokcevic703849e2023-08-16 00:13:3434 gclient-condition = checkout_linux
Josip Sokcevic79a4a542023-08-15 00:35:0835```
36
37gitlink entry, retrieved using `git ls-files -s -- third_party/catapult`:
38
39```
40160000 0b39a694c0b61392d1180520ed1c13e390029c41 0 third_party/catapult
41```
42
43Corresponding DEPS entry would look like:
44
45```
46 'third_party/catapult': {
Josip Sokcevic703849e2023-08-16 00:13:3447 'url': 'https://chromium.googlesource.com/catapult.git@0b39a694c0b61392d1180520ed1c13e390029c41',
48 'condition': 'checkout_linux',
Josip Sokcevic79a4a542023-08-15 00:35:0849}
50```
51
52## How to avoid accidental Git submodule updates?
53
54The simplest approach is to always run gclient sync after updated chromium
55checkout (e.g. after `git pull`, or `git checkout`). You can automate that by
56adding post-checkout hook (example below). To confirm there are no changes, run
57`git status`. If you use `git commit -a`, check the "Changes to be committed"
58section that shows up in the edit commit message.
59
60### Automatically run gclient sync after git pull / git checkout
61
62We need to have Git two hooks: post-checkout and post-merge. In chromium/src
63directory, edit `.git/hooks/post-checkout`:
64
65```
66#!/bin/sh
67
68set -u
69gclient sync
70```
71
72and set it to be executable: `chmod +x .git/hooks/post-checkout`. Repeat the
73same for `.git/hooks/post-merge`.
74
75More information about githooks can be found
76[here](https://git-scm.com/docs/githooks).
77
78### Git status shows modified dependencies. What does that mean?
79
80If a submodule is checked out at a different commit than one tracked by its
81parent, `git status` in the parent repo will show unstaged changes with "new
82commits" in parenthesis, such as:
83
84```
85modified: <git deps name> (new commits)
86```
87
88Commands like `git commit -a` or `git add *|.|-A|u` WILL include this in your
89commit and your CL (which is likely NOT what you want).
90
91Instead you can:
92
93```
94# Run gclient sync to sync dependencies
95gclient sync
96# check git status again
97
98# OR
99git add <file> # for each file you want to stage
100# Then commit your staged files
101git commit -v -m "Fix foo/bar"
102```
103
Josip Sokcevic15a05752023-08-24 17:02:20104NOTE: due to a bug in gclient (crbug.com/1475448), it's possible that gclient
105left unmanaged git repository. You may need to manually remove those unmanaged
106repositories.
107
108```
109# Inside chromium/src checkout:
110# This ensures that all managed dependencies are in sync:
111gclient sync -D
112# This moves all unused dependencies to ../unused directory in gclient root
113# (just outside of src directory). It then tells git to restore gitlink.
114for f in $( git status | grep '(new commits)' | awk '{print $2}' ); do mkdir -p "../unused/`dirname $f`" && mv $f "../unused/$f" && git checkout -- $f; done
115# inspect ../unused/ if you'd like, and remove it there's nothing useful there,
116# e.g. no non-uploaded commits.
117```
118
Josip Sokcevic79a4a542023-08-15 00:35:08119If a submodule has uncommitted changes (i.e. you made some manual changes to the
120affected submodule), running `git status` in its parent repo will show them as
121unstaged changes:
122
123```
124 modified: <git deps name> (modified content)
125
126# or
127
128 modified: <git deps name> (untracked content)
129```
130
131It's not possible to add those changes to the parent repository. You can ignore
132such status, or you can cd into submodule and address it. E.g. you may delete
133untracked files (content) or reset modified content to match HEAD.
134
135## I accidentally staged Git submodule (not yet committed)
136
137If you accidentally stage a Git submodule, you can unstage it by running `git
138restore --staged <path to submodule>`.
139
140## I accidentally committed Git submodule
141
142We will need to create either a commit that sets it back to old value, or amend
143the commit that added it. You can try to run `gclient sync` to bring the commit
144back to what is expected. If that doesn't work, you can use `gclient setdep -r
Josip Sokcevic00eefc52023-08-27 22:11:27145<path>@<old hash>`, run `gclient gitmodules` to sync all submodules commits back
Josip Sokcevic79a4a542023-08-15 00:35:08146to what is in DEPS, or check detailed instructions in [Managing
147dependencies](dependencies.md).
148
Josip Sokcevic00eefc52023-08-27 22:11:27149NOTE: setdep for chromium/src is always prefixed with src/. For example, if you
150are updating v8, the command would be `gclient setdep -r src/v8@<hash>.
151
Joanna Wangeda00e42023-09-20 18:51:47152## BETA: Install a hook to help detect unintentional submodule commits
153
154depot_tools provides an opt-in pre-commit hook to detect unintentional submodule
155 changes during `git commit` and remove them from the commit.
156
157To install the hook: `gclient installhooks`
158
159If there is an existing pre-commit hook, gclient will instruct you how to update
160it. If you have already installed this hook, gclient will do nothing.
161
162To uninstall the hook, in `chromium/src` `rm .git/hooks/pre-commit` if you have
163no other hooks. Otherwise update `.git/hooks/pre-commit` to remove the gclient
164provided hook.
165
166To bypass this hook run `git commit --no-verify` (which bypasses all hooks you
167 may have) OR set the following environment variable: `SKIP_GITLINK_PRECOMMIT=1`
168(which bypasses this specific hook).
169
170Note that this is currently and best effort solution and does not guarantee
171that unintentional commits will always be detected. The team will iterate
172quickly on this hook to fill in other gaps and behavior is subject to change.
173Please file an [issue](https://bugs.chromium.org/p/chromium/issues/entry?components=Infra%3ESDK&labels=submodules-feedback&[email protected],[email protected]&description=Please%20steps%20to%20reproduce%20the%20problem:%0A%0ADo%20you%20have%20any%20custom%20environment%20setups%20like%20git%20hooks%20or%20git%20configs%20that%20you%20have%20set%20yourself%0A%0APlease%20attach%20output%20of:%0Agit%20config%20-l%0Agit%20map-branches%20-vv%0A%0AIf%20this%20is%20an%20issue%20with%20git%20cl%20upload%20please%20include%20the%20git%20trace%20file%20for%20the%20problematic%20run%20found%20in:%0A%3Cdepot_tools_path%3E/traces/%3Clatest%20trace%3E) for any feedback.
174
Josip Sokcevic79a4a542023-08-15 00:35:08175## FAQ
176
177### Why do we have Git dependencies in both DEPS and Git submodules?
178
179Lots of Chromium infrastructure already parse DEPS file directly. Instead of a
180massive switch, it's easier to transition to Git submodules this way. Moreover,
181unwanted Git submodule updates can be detected and developers can be warned.
182
183### How do I manually roll Git submodule?
Josip Sokcevic00eefc52023-08-27 22:11:27184
Josip Sokcevic79a4a542023-08-15 00:35:08185See the [dependencies](dependencies.md) page.
186
Josip Sokcevic00eefc52023-08-27 22:11:27187### I got a conflict on a submodule, how do I resolve it?
188
189First, you will need to determine what is the right commit hash. If you
190accidentally committed a gitlink, which got in the meantime updated, you most
191likely want to restore the original updated gitlink. You can run `gclient
192gitmodules`, which will take care of all unmerged submodule paths, and set it to
193match DEPS file.
194
195If you prefer to manually resolve it, under git status, you will see "Unmerged
196paths". If those are submodules, you want to restore them by running the
197following command:
198
199```
200git restore --staging <affected path>
201```
202
Joanna Wangb812e222023-08-31 17:43:53203### How do I see what revision is pinned?
204
205`gclient getdep` will return whatever commit is pinned for the deps in `DEPS`
206(unstaged, staged, or committed). If the repo is using git submodules only
207(and has no git deps in `DEPS`) it will return the whatever pinned commit is
208staged or committed.
209
210```
211gclient getdep -r <path>
212```
213
214
Josip Sokcevic00eefc52023-08-27 22:11:27215If you want to keep your gitlink, then run `git add <affected path>`.
216
Josip Sokcevic79a4a542023-08-15 00:35:08217### How can I provide feedback?
218
219Please file [a bug under Infra>SDK
220component](https://bugs.chromium.org/p/chromium/issues/entry?components=Infra%3ESDK).
221