Infrastructure/GitLab: Difference between revisions
m →Submitting a merge request: consistency only |
Perikiyoxd (talk | contribs) m Removed forced language when visiting keysmith link |
||
(69 intermediate revisions by 19 users not shown) | |||
Line 3: | Line 3: | ||
{{Info|The KDE community does not generally use GitLab for bug reporting. Please continue to submit bug reports on https://bugs.kde.org. Task management is transitioning to Invent/GitLab but most projects still use https://phabricator.kde.org for now.}} | {{Info|The KDE community does not generally use GitLab for bug reporting. Please continue to submit bug reports on https://bugs.kde.org. Task management is transitioning to Invent/GitLab but most projects still use https://phabricator.kde.org for now.}} | ||
== Logging in == | |||
Navigate to https://invent.kde.org/users/sign_in and log in using the username and password for your KDE Identity account. | |||
If you don't have an KDE Identity already you can [https://identity.kde.org/index.php?r=registration/index sign up for one here]. You will be required to provide a name and an email address. When selecting your username, please select something which has a relation to your real name. These details will be synced to GitLab once you have logged in and will also become your primary Git email address. You may receive some email spam as a consequence. | |||
{{Note|It is recommended that you use the same email address across all KDE services, including [http://bugs.kde.org bugs.kde.org], or else the merge request hookscripts that automatically close bugzilla tickets won't work. If you don't have an account in [http://bugs.kde.org bugs.kde.org] already, please create one as well.}} | |||
{{Note|If you are a KDE developer, you are required to set up Two-Factor-Authentication (2FA). This can be done using either a Webauthn token (such as a Yubikey) or Time-based one-time password (TOTP) generated using the app of choice (such as [https://apps.kde.org/keysmith/ KDE Keysmith]). Should you lose access to your 2FA device you can obtain a recovery token to log back in via SSH, as described in the [https://invent.kde.org/help/user/profile/account/two_factor_authentication.md#generate-new-recovery-codes-using-ssh GitLab Documentation].}} | |||
You will need to set up git to use | === Setting up Git === | ||
You will need to set up git to use your account details to help identify your work. Make sure that these details match your GitLab profile, otherwise commits can't be traced back to your account. | |||
<syntaxhighlight lang="bash"> | <syntaxhighlight lang="bash"> | ||
git config user.name | $ git config --global user.name "Your Real Name" | ||
git config user.email | $ git config --global user.email "Your identity.kde.org email" | ||
</syntaxhighlight> | </syntaxhighlight> | ||
In order to authenticate yourself when pushing code changes, you need to add a SSH key to your GitLab profile as [https://invent.kde.org/help/user/ssh.md described here]. | |||
== Submitting a merge request == | |||
When making large changes to any KDE source code, we organize work into '''Merge Requests'''. They are a collection of one or many commits that you want to merge into the master branch. | |||
== Submitting a | |||
=== Build the project from source and make your change === | === Build the project from source and make your change === | ||
Line 37: | Line 30: | ||
=== Fork the project === | === Fork the project === | ||
{{Note|If you have commit access, you can prefix your branches with | {{Note|If you have commit access, you can prefix your branches with <code>work/</code> to push them directly to origin without having to fork and safely ignore this section.}} | ||
Once you have made some local changes that you would like to submit to KDE, you need to create a personal fork of the project and push your changes to the forked copy. | Once you have made some local changes that you would like to submit to KDE, you need to create a personal fork of the project and push your changes to the forked copy. | ||
Navigate to https://invent.kde.org/ | Navigate to https://invent.kde.org/explore/groups and locate the project. If it is not visible in the list, you can use the search field. Once you find the project, click on it: | ||
[[File:Find_the_project.png|600px]] | [[File:Find_the_project.png|600px]] | ||
On the project's page, click on the "Fork" button in the top-right corner of the screen: | On the project's page, click on the '''"Fork"''' button in the top-right corner of the screen: | ||
[[File:Click_the_Fork_button.png|300px]] | [[File:Click_the_Fork_button.png|300px]] | ||
This will take you to a page asking you some details about how you want to fork the project. Select | This will take you to a page asking you some details about how you want to fork the project. Select '''Your Name''' in the '''"Project URL"''' section and '''"Public"''' in the '''"Visibility level"''' section: | ||
[[File:Choose_the_fork_namespace.png|700px]] | [[File:Choose_the_fork_namespace.png|700px]] | ||
After a moment, the system will finish creating the fork and take you to the page for your fork. On that page, click on the blue "Clone" button in the top-right corner: | After a moment, the system will finish creating the fork and take you to the page for your fork. On that page, click on the blue '''"Clone"''' button in the top-right corner: | ||
[[File:Click_the_Clone_button.png|300px]] | [[File:Click_the_Clone_button.png|300px]] | ||
In the pop-up that appears, click on the " | In the pop-up that appears, click on the '''"Copy"''' button to the right of the upper text field. This will copy the URL for the fork onto your clipboard. | ||
[[File:Copy_the_URL.png|300px]] | [[File:Copy_the_URL.png|300px]] | ||
If the blue '''"Clone"''' button is missing, append '''.git''' to the URL of the current page and copy this. | |||
=== Clone the repository to your local environment === | |||
{{Input|1=<nowiki> | |||
git clone [the URL you copied to your clipboard] | |||
</nowiki>}} | |||
{{Input|1=<nowiki> | |||
cd [the name of the repository] | |||
</nowiki>}} | |||
If you need to verify Invent's ssh host fingerprint, these can be found here: https://invent.kde.org/help/instance_configuration | |||
=== Add the fork to your source checkout === | === Add the fork to your source checkout === | ||
Next, open your terminal app and navigate to the location where the project's repo lives (i.e. | Next, open your terminal app and navigate to the location where the project's repo lives (i.e. {{Path|~/kde/src/[the project name]}}). | ||
You need to add your fork as a '''remote''' to the existing repo: | You need to add your fork as a '''remote''' to the existing repo: | ||
Line 70: | Line 77: | ||
</nowiki>}} | </nowiki>}} | ||
Run | Run '''"git remote -v"'''. You should see something like this: | ||
<pre> | <pre> | ||
Line 80: | Line 87: | ||
</pre> | </pre> | ||
This means you have two remotes set up for your repo: "origin" points to the original repo, and "fork" points to your fork of it. | This means you have two remotes set up for your repo: '''"origin"''' points to the original repo, and '''"fork"''' points to your fork of it. | ||
=== Make a branch and commit === | === Make a branch and commit === | ||
Line 91: | Line 98: | ||
</nowiki>}} | </nowiki>}} | ||
{{Note|If you have commit access and are pushing a branch directly to origin, remember to prefix your branch with | It is important to create a git branch in your git fork remote, and not use the git master branch. This is because the master git branch in the fork git remote is tracking the master git branch in origin. By not using the master branch in fork, you will be able to do git rebase. | ||
{{Note|If you have commit access and are pushing a branch directly to origin, remember to prefix your branch with <code>work/</code>. Branches with this prefix can be force-pushed to and keywords like <code>BUG:</code> are not evaluated}} | |||
=== Write a good commit message === | === Write a good commit message === | ||
Please follow [https://chris.beams.io/posts/git-commit/#seven-rules commit message best practices]: write a descriptive title in the form of an imperative sentence (e.g. "Fix button disappearing when view is changed") and on the next line, write at least one sentence describing your change and why it is necessary, adding more details if necessary. | Please follow [https://chris.beams.io/posts/git-commit/#seven-rules commit message best practices]: write a descriptive title in the form of an imperative sentence (e.g. "Fix button disappearing when view is changed") and on the next line, write at least one sentence describing your change and why it is necessary, and adding more details if necessary. | ||
If your patch is intended to fix a Bugzilla ticket, include the following on its own line: | If your patch is intended to fix a Bugzilla ticket, include the following on its own line: | ||
Line 115: | Line 124: | ||
[https://community.kde.org/Policies/Commit_Policy#Special_keywords_in_GIT_and_SVN_log_messages Here is more information] about other special messages that interact with Bugzilla tickets. | [https://community.kde.org/Policies/Commit_Policy#Special_keywords_in_GIT_and_SVN_log_messages Here is more information] about other special messages that interact with Bugzilla tickets. | ||
{{Note|These keywords will only work if the email address in your | {{Note|These keywords will only work if the email address in your {{Path| ~/.config/git/config}} file matches the email address used for your https://bugs.kde.org account (See [https://techbase.kde.org/Development/Git/Configuration#Basic_Settings this page] for more information).}} | ||
=== Push to your fork === | === Push to your fork === | ||
At this point you have a branch in your local | At this point you have a branch in your local repository called "my_awesome_feature" (Hopefully, in reality, it is named something a bit more appropriate!) that has a commit on it with your work. Now push it to your fork: | ||
{{Input|1=<nowiki> | {{Input|1=<nowiki> | ||
Line 124: | Line 133: | ||
</nowiki>}} | </nowiki>}} | ||
{{Note|This will only work if you previously added an SSH key to your GitLab profile. See [https://invent.kde.org/help/user/ssh.md https://invent.kde.org/help/user/ssh.md] on how to create an SSH key and how to add it to your GitLab profile.}} | |||
This will produce a message somewhat like this: | This will produce a message somewhat like this: | ||
Line 144: | Line 154: | ||
</pre> | </pre> | ||
=== Create the | === Create the merge request === | ||
Notice the "To create a merge request for my_awesome_feature..." message in the output of the push command (explained in the previous section). You can copy-and-paste the URL shown below it into a web browser. On some terminal apps, such as Konsole and Yakuake, you can ctrl+click on the link to go right there! | Notice the "To create a merge request for my_awesome_feature..." message in the output of the push command (explained in the previous section). You can copy-and-paste the URL shown below it into a web browser. On some terminal apps, such as Konsole and Yakuake, you can ctrl+click on the link to go right there! | ||
Line 151: | Line 161: | ||
[[File:Merge_Request_info.png|800px]] | [[File:Merge_Request_info.png|800px]] | ||
In the Description section, write at least one sentence describing your change and why it is necessary, adding more details if needed. | In the Description section, write at least one sentence describing your change and why it is necessary, adding more details if needed. Tag any of the following teams in the description text based on what kind of review you would like: | ||
* General QA review: '''@teams/qa''' | |||
* Visual and UI review: '''@teams/vdg''' (please add before-and-after screenshots) | |||
* Usability review: '''@teams/usability''' | |||
* Questions about translations: '''@teams/localization''' | |||
If your patch is related to any existing issue or merge request on Invent, be sure to paste the link to them in the description. Connecting related issues and MRs makes them significantly easier to find, both for you and for others later on. | |||
If your patch is intended to fix a Bugzilla ticket, include the ticket number at the bottom of the description, just like how you did in the commit message (as explained in [[Infrastructure/GitLab#Write_a_good_commit_message]]): | If your patch is intended to fix a Bugzilla ticket, include the ticket number at the bottom of the description, just like how you did in the commit message (as explained in [[Infrastructure/GitLab#Write_a_good_commit_message]]): | ||
Line 171: | Line 188: | ||
Once the Merge Request is accepted, KDE Developers will merge it for you! | Once the Merge Request is accepted, KDE Developers will merge it for you! | ||
=== Making changes to a | === Making changes to a merge request === | ||
Oftentimes, reviewers will request changes before the Merge Request can be merged. To accomplish this | Oftentimes, reviewers will request changes before the Merge Request can be merged. To accomplish this you need to make the requested changes locally and then create a new commit including your changes. First, stage all changed files: | ||
{{Input|1=<nowiki> | {{Input|1=<nowiki> | ||
Line 189: | Line 206: | ||
</nowiki>}} | </nowiki>}} | ||
=== Rebasing a | === Rebasing a merge request === | ||
When other changes have been made to the project's source code repo since you submitted your Merge Request, you will need to ''rebase'' the Merge Request to incorporate those changes. | When other changes have been made to the project's source code repo since you submitted your Merge Request, you will need to ''rebase'' the Merge Request to incorporate those changes. | ||
Line 230: | Line 247: | ||
</syntaxhighlight>}} | </syntaxhighlight>}} | ||
At this point | At this point there may be merge conflicts. If there are, git will tell you which files have conflicts. You can then open each file and resolve the conflict by editing the contents to keep only the appropriate change. In order to accomplish that you can either make each change manually or you can use <code>git mergetool</code> which will open a diff tool of your choice (if there's any installed). | ||
If you use a diff tool like '''meld''', for | If you use a diff tool like '''meld''', for example, the origin will be shown on the left, your fork will be shown on the right, and you may pick which changes to apply to the middle file, the new one. | ||
After resolving the existing conflicts, run <code>git add [file path]</code> on each conflicted file once all the conflicts have been resolved. Lastly, run <code>git rebase --continue</code> to finish the rebase. | After resolving the existing conflicts, run <code>git add [file path]</code> on each conflicted file once all the conflicts have been resolved. Lastly, run <code>git rebase --continue</code> to finish the rebase. | ||
Line 246: | Line 263: | ||
}} | }} | ||
=== Cherry-picking a | === Cherry-picking a merge request's git commit to another branch === | ||
If a Merge Request was labeled with the "cherry-pick" label, it should be manually cherry-picked to the branch corresponding to target milestone after it is merged to master. To do this, click on the link to the commit that was generated: | If a Merge Request was labeled with the "cherry-pick" label, it should be manually cherry-picked to the branch corresponding to the target milestone after it is merged to master. To do this, click on the link to the commit that was generated: | ||
[[File:Click on this to get to the commit.png|700px]] | [[File:Click on this to get to the commit.png|700px]] | ||
On that page, click the "Options" button and then "Cherry-Pick" from its | On that page, click the "Options" button and then "Cherry-Pick" from its drop-down menu: | ||
[[File:Cherry-pick it.png|700px]] | [[File:Cherry-pick it.png|700px]] | ||
In the dialog that appears, select the branch you want to cherry-pick the commit to | In the dialog that appears, select the branch you want to cherry-pick the commit to, and then click the "Cherry-Pick" button. This will create a new merge request for the change. Set it to auto-merge once the pipeline is successful. '''If the pipeline fails, it is your responsibility to figure out what went wrong and fix it!''' | ||
You can also manually cherry-pick the commit using the git command line. When doing so, always add the <code>-x</code> option to <code>git-cherry-pick</code>. '''This is not recommended because it bypasses the CI pipeline.''' Making a merge request via the web UI is preferred. | |||
[[ | == Testing someone else's merge request == | ||
First you'll need to set up a development environment, if you haven't already. To do this, follow [[Get_Involved/development#Set_up_your_development_environment|the instructions here]]. | |||
Once your development environment is set up, you can use the '''git mr''' tool to check out local branches for people's merge requests so you can compile and test them. This tool lives in the [https://github.com/tj/git-extras Git Extras] project, and is typically packaged by distros under the name "git-extras". Here's how to install it for various Linux distributions: | |||
'''Arch Linux''' | |||
* The '''git-extras''' package is not available in the Arch Linux repositories, only the AUR, so it needs to be built and installed with makepkg. | |||
* For more information on using makepkg refer to its [https://man.archlinux.org/man/makepkg.8.en manual] or [https://wiki.archlinux.org/title/makepkg Arch Linux Wiki entry]. | |||
{{Input|1=<nowiki> | {{Input|1=<nowiki> | ||
cd /tmp | |||
git clone https://aur.archlinux.org/git-extras.git | |||
cd ./git-extras | |||
makepkg -si | |||
cd /tmp | |||
rm -rd /tmp/git-mr | |||
</nowiki>}} | </nowiki>}} | ||
'''Debian | '''Debian, Ubuntu, & KDE Neon''' | ||
{{Input|1=<nowiki> | {{Input|1=<nowiki> | ||
sudo apt install git-extras | sudo apt install git-extras | ||
</nowiki>}} | </nowiki>}} | ||
''' Fedora ''' | '''Fedora''' | ||
{{Input|1=<nowiki> | {{Input|1=<nowiki> | ||
sudo dnf install git-extras | sudo dnf install git-extras | ||
</nowiki>}} | </nowiki>}} | ||
''' | '''Manjaro''' | ||
* The '''git-extras''' package is not available in the Manjaro repositories, only the AUR, so it needs to be built and installed with pamac. | |||
{{Input|1=<nowiki> | |||
pamac build git-extras | |||
</nowiki>}} | |||
'''openSUSE Leap 15.5''' | |||
* The '''git-extras''' package is not available in the default openSUSE 15.5 repositories but it is available in the experimental [https://build.opensuse.org/project/show/devel:tools:scm devel:tools:scm repository]. | |||
{{Input|1=<nowiki> | |||
sudo zypper addrepo https://download.opensuse.org/repositories/devel:tools:scm/15.5/devel:tools:scm.repo | |||
sudo zypper refresh | |||
sudo zypper install git-extras | |||
</nowiki>}} | |||
'''openSUSE Tumbleweed''' | |||
* The '''git-extras''' package is not available in the default openSUSE Tumbleweed repositories but it is available in the experimental [https://build.opensuse.org/project/show/devel:tools:scm devel:tools:scm repository]. | |||
{{Input|1=<nowiki> | |||
sudo zypper addrepo https://download.opensuse.org/repositories/devel:tools:scm/openSUSE_Tumbleweed/devel:tools:scm.repo | |||
sudo zypper refresh | |||
sudo zypper install git-extras | |||
</nowiki>}} | |||
* While the '''git-extras''' package is not available in the default openSUSE Tumbleweed repositories, the '''git mr''' tool itself has been packaged standalone and is available for those that don't want or need the full git-extras package. | |||
{{Input|1=<nowiki> | {{Input|1=<nowiki> | ||
sudo zypper install git-mr | sudo zypper install git-mr | ||
</nowiki>}} | </nowiki>}} | ||
=== Check out the | === Check out the merge request and compile the software === | ||
First check out or enter the source repository for the software that's being patched. For example, let's say you want to test a Merge Request for Okular. If you've never built it before, check it out and build it once first: | First check out or enter the source repository for the software that's being patched. For example, let's say you want to test a Merge Request for Okular. If you've never built it before, check it out and build it once first: | ||
{{Input|1=<nowiki> | {{Input|1=<nowiki> | ||
kde-builder okular | |||
</nowiki>}} | </nowiki>}} | ||
Line 295: | Line 341: | ||
</nowiki>}} | </nowiki>}} | ||
Find the Merge Request's ID. For example, for https://invent.kde.org/kde/okular/merge_requests/80, the ID is | Find the Merge Request's ID. For example, for https://invent.kde.org/kde/okular/merge_requests/80, the ID is '''80'''. | ||
...and apply the Merge Request: | ...and apply the Merge Request: | ||
Line 304: | Line 350: | ||
Now it's time to compile and run the software to make sure that the Merge Request does what it says it does and doesn't cause any regressions! Compile the patched source code: | Now it's time to compile and run the software to make sure that the Merge Request does what it says it does and doesn't cause any regressions! Compile the patched source code: | ||
{{Input|1=<nowiki> | {{Input|1=<nowiki> | ||
kde-builder okular --no-src --no-include-dependencies | |||
</nowiki>}} | </nowiki>}} | ||
Those arguments will tell | Those arguments will tell '''kde-builder''' to not update the source code and to not build any dependencies. | ||
If it didn't compile, that's reason alone to reject the Merge Request! Go to the web page for the Merge Request and report your findings. | If it didn't compile, that's reason alone to reject the Merge Request! Go to the web page for the Merge Request and report your findings. | ||
=== Perform QA === | === Perform QA === | ||
If it did compile, then it's time to perform QA | If it did compile, then it's time to perform QA because it's important to thoroughly test Merge Requests to ensure that bad code and regressions don't slip in. '''This is the entire purpose of having a review infrastructure and it is very important!''' | ||
First make sure the unit tests all pass: | First make sure the unit tests all pass: | ||
{{Input|1=<nowiki> | {{Input|1=<nowiki> | ||
cd ~kde/build/kde/applications/okular | cd ~kde/build/kde/applications/okular | ||
ctest | source prefix.sh | ||
ctest --output-on-failure | |||
</nowiki>}} | </nowiki>}} | ||
If any tests fail, report this through a comment on the Merge Request's web page. | If any tests fail, report this through a comment on the Merge Request's web page. | ||
Next, if it's not clear how to test the Merge Request, leave a comment gently explaining this and asking for the submitter to change the Description section to describe how to test it. | |||
Once you know how to test the Merge Request, use the software with the Merge Request applied. Test whether it crashes on launch, whether the main UI appears, and so on. If the Merge Request references any bug reports, read them, understand what issue they are reporting, and test the change to make sure it fixes the bugs. | |||
Try to avoid reviewing parts of the software that have not been changed by the Merge Request, or proposing changes that are unrelated to the Merge Request. It's common to see a screenshot of a change and get ideas for other things that could be improved in the future, but try to avoid bringing those up in the Merge Request itself! Instead discuss those topics elsewhere later. | |||
Next, try to break the Merge Request. Here are some ideas: | Next, try to break the Merge Request. Here are some ideas: | ||
# Remove the program's configuration file ( | # Remove the program's configuration file ({{Path |~/.config/<program name>rc}}) and re-open it | ||
# Try the program with | # Try the program with multiple HiDPI scale factors and without one at all, different font sizes, or languages known to have long text like German or Brazilian Portuguese | ||
# If it's a new feature, feed it unexpected input | # If it's a new feature, feed it unexpected input | ||
# Test related functionality | # Test related functionality | ||
A good Merge Request will handle corner cases and variations in configuration. The price of configurability is vigilant testing! We owe it to our users to test using many configurations, not just the defaults or our personal settings. | A good Merge Request will handle corner cases and variations in configuration. The price of configurability is vigilant testing! We owe it to our users to test using many configurations, not just the defaults or our personal settings. | ||
If the result of your testing is positive because the change fixes all referenced bugs and causes no regressions, leave a comment mentioning that you performed QA and are approving on the basis of QA, and click the Approve button! | |||
If not, apply the '''"Needs Changes"''' label and write a comment describing the issues you discovered. It is permissible to do this even if you have not been specified as a reviewer! '''Anyone can reject a Merge Request on the grounds that it does not work, does not do what it says it does, or causes regressions.''' | |||
=== Perform code review === | === Perform code review === | ||
Code review is a complex topic, but anyone can learn how to do it well! Here are some resources that can help: | |||
* https://google.github.io/eng-practices/review/reviewer/ | |||
* https://philbooth.me/blog/the-art-of-good-code-review | |||
=== Engage with the author and other reviewers === | === Engage with the author and other reviewers === | ||
After you have run the program and evaluated the Merge Request, it's time to leave some review comments on the webpage. If you have been specified as a reviewer, or are a member of a group that has been specified as a reviewer, it is permissible to Accept the Merge Request. | After you have run the program and evaluated the Merge Request, it's time to leave some review comments on the webpage. If you have been specified as a reviewer, or are a member of a group that has been specified as a reviewer, it is permissible to Accept the Merge Request. Keep in mind that reviewing involves responsibility: you are giving a thumbs-up to code that will be run potentially by millions of people. If you accept and land a Merge Request that causes regressions, you will be expected to help fix it if the original author cannot or has disappeared. '''It is important to take the reviewer role seriously.''' | ||
== Advanced topics == | == Advanced topics == | ||
Line 342: | Line 398: | ||
=== Curating your merge request commit history === | === Curating your merge request commit history === | ||
For large or complex merge requests, it is strongly recommended to separate the pieces of your proposed change into individual commits--one for each component of the proposed change. For example, perhaps you are working on a feature that consists of multiple logically separable elements that nonetheless all live in the same source repo, or perhaps you are first doing some code refactoring, then you add a backend feature, then finally you add a front-end user interface for it. | For large or complex merge requests, it is strongly recommended to separate the pieces of your proposed change into individual commits--one for each component of the proposed change. For example, perhaps you are working on a feature that consists of multiple logically separable elements that nonetheless all live in the same source repo, or perhaps you are first doing some code refactoring, then you add a backend feature, then finally you add a front-end user interface for it. | ||
For this workflow, specifically mention in the merge request description that you would like reviewers to review individual commits separately, and not squash when merging. | For this workflow, specifically mention in the merge request description that you would like reviewers to review individual commits separately, and not squash when merging. | ||
If you need to later make changes to your Merge Request, do not add new commits; instead, combine the new changes with one of the existing commits using | If you need to later make changes to your Merge Request, do not add new commits; instead, combine the new changes with one of the existing commits using Git's interactive rebasing feature. To learn how to do this, see https://git-rebase.io/ | ||
{{Note|Using | {{Note|Using GitLab's "Apply suggestion" feature will create new commits in your Merge Request which must be manually squashed into one of the existing commits.}} | ||
=== Using work branches instead of forks === | === Using work branches instead of forks === | ||
If you have a [[Infrastructure/Get a Developer Account|developer account]], you don't need to use forks to submit merge requests. Instead, make sure your branch name begins with | If you have a [[Infrastructure/Get a Developer Account|developer account]], you don't need to use forks to submit merge requests. Instead, make sure your branch name begins with {{ic|work/}} and push it straight to the main repo. {{ic|work/}} branches are treated specially, as you can use {{ic|git push --force}} with them. By convention, it is recommended to add your KDE username to the branch, so the final name would end up looking like {{ic|work/your-username/my-awesome-feature}}. | ||
To make it easier creating new | To make it easier creating new {{ic|work}} branches (instead of typing work/your-username/branch-name every time), you can use a Git script to do that; for example, if you create a shell script somewhere in your {{ic|PATH}}, and name it e.g. {{ic|git-work}} (the script name must start with '''git-'''), and make the script executable: | ||
{{ | |||
{{hbc-hl|bash|git-work| | |||
#!/usr/bin/bash | #!/usr/bin/bash | ||
if [ -z "$1" ]; then | if [ -z "$1" ]; then | ||
Line 362: | Line 419: | ||
fi | fi | ||
git checkout | git checkout -b work/your-user-name/$1 | ||
}} | |||
you can then use: | |||
{{ | {{bc| | ||
git work branch-name | git-work branch-name | ||
}} | |||
which will create a branch called {{ic|work/your-username/branch-name}} that tracks {{ic|origin/master}} and then switches to the newly created branch. | |||
=== Switching the target branch of a | === Switching the target branch of a merge request === | ||
Sometimes you will submit a merge request that is targeting the master branch, but will later be asked to target the stable branch instead because it is a bugfix | Sometimes you will submit a merge request that is targeting the master branch, but will later be asked to target the stable branch instead because it is a bugfix or, perhaps, you have targeted the stable branch but the commit is considered too invasive and you are asked to target the master branch instead. In either of those circumstances you will need to re-target your Merge Request. Here's how: | ||
{{Input|1=<nowiki> | {{Input|1=<nowiki> | ||
Line 382: | Line 439: | ||
</nowiki>}} | </nowiki>}} | ||
This will open a text editor showing a list of commits, each on a separate line. Delete all of the lines of text except for the ones corresponding to new commits you have added as part of your merge request. Next, fix any merge conflicts if there are any. | This will open a text editor showing a list of commits, each on a separate line. '''Delete all of the lines of text except for the ones corresponding to new commits you have added as part of your merge request.''' Next, fix any merge conflicts if there are any. | ||
Then force-push the branch up to | Then force-push the branch up to GitLab again: | ||
{{Input|1=<nowiki> | {{Input|1=<nowiki> | ||
Line 390: | Line 447: | ||
</nowiki>}} | </nowiki>}} | ||
Finally, edit the merge request by clicking the "Edit" button in the top-right corner of the page and choose the desired different target branch: | Finally, edit the merge request by clicking the '''"Edit"''' button in the top-right corner of the page and choose the desired different target branch: | ||
[[File:Editing_merge_request_target_branch.png]] | [[File:Editing_merge_request_target_branch.png]] | ||
Note that after merging a Merge Request to the stable branch, you are expected to merge that branch back to < | Note that after merging a Merge Request to the stable branch, you are expected to merge that branch back to <code>master</code> afterwards: | ||
{{Input|1=<nowiki> | {{Input|1=<nowiki> | ||
git fetch origin | |||
git checkout release/19.12 | git checkout release/19.12 | ||
git pull | git pull | ||
Line 405: | Line 463: | ||
</nowiki>}} | </nowiki>}} | ||
{{ | {{Warning|If at any time you feel nervous or run into trouble, ask your reviewers for help. This can be tricky and undoing bad merges is a pain in the neck.}} | ||
=== Requesting exceptions to feature or string freezes === | |||
Many KDE products are affected by a ''feature freeze'' or a ''string freeze'' at various points in their development. The timing of these freezes are indicated on the product pages linked to [[Schedules|here]]. Sometimes the people reviewing your merge request will tell you that an exception to one of these freezes will be required before it can be merged. To request one, send an email to the relevant mailing list: | |||
* For a string freeze exception, email [email protected] | |||
* For a feature freeze exception for software on the Plasma release schedule, email [email protected] | |||
* For a feature freeze exception for software on the KDE Gear release schedule, email [email protected] | |||
* For a feature freeze exception for anything else, email [email protected] | |||
Here's a sample email: | |||
<blockquote> | |||
Hello [translators/fellow developers!] | |||
I'd like to request a [string/feature] freeze exception for [insert URL of your merge request]. I feel that this is important to get into the next release because [insert convincing reason here]. | |||
As I am not subscribed to this mailing list, please use "Reply All" rather than "Reply List". [can be omitted if you are in fact subscribed to the mailing list] | |||
Thanks! | |||
</blockquote> | |||
A string freeze exception is considered granted once translators from at least two teams have approved and none have disapproved. | |||
A feature freeze exception is considered granted once two developers approve and no one has disapproved. | |||
=== Pushing commits to somebody else's fork === | === Pushing commits to somebody else's fork === | ||
Sometimes someone will say " | Sometimes someone will say "Hey, let's work on my branch together," so you will be pushing commits to neither origin nor your fork, but to someone else's fork. Let's say you are asked to help work on joliveira's "gsoc2019_numberFormat" branch. | ||
First you would need to add the URL for his fork as a remote: | First, you would need to add the URL for his fork as a remote: | ||
<pre> | <pre> | ||
Line 432: | Line 513: | ||
</nowiki>}} | </nowiki>}} | ||
This will download the list of branches. The next step is to switch to the one you want to collaborate on: | This will download the list of branches. The next step is to switch to the one you want to collaborate on: | ||
{{Input|1=<nowiki> | {{Input|1=<nowiki> | ||
Line 438: | Line 519: | ||
</nowiki>}} | </nowiki>}} | ||
This will create a local branch named "gsoc2019_numberFormat" from the contents of the remote branch joliveira_fork/gsoc2019_numberFormat and that also "tracks" it. This means that if someone else pushes changes to a remote version of that branch | This will create a local branch named "gsoc2019_numberFormat" from the contents of the remote branch joliveira_fork/gsoc2019_numberFormat and that also "tracks" it. This means that if someone else pushes changes to a remote version of that branch then you can run <code>git pull --rebase</code> while on your local "gsoc2019_numberFormat" branch to bring it up to date. | ||
Next, make your changes, add and commit. Then push the changes to the remote joliveira_fork remote: | Next, make your changes, add and commit. Then push the changes to the remote joliveira_fork remote: | ||
Line 449: | Line 530: | ||
History has taught that no system used by KDE around the code repositories stays forever. | History has taught that no system used by KDE around the code repositories stays forever. | ||
Quickgit, CGit, Phabricator & Co. came and at one point were replaced | Quickgit, CGit, Phabricator & Co. came and at one point were replaced while, sadly, also taking with them their service-specific URLs (and host names). | ||
To give documentation, blog posts, commit messages and other long-living documents a way to reference commits or objects in the repository like directories or files | To give documentation, blog posts, commit messages, and other long-living documents a way to reference commits or objects in the repository, like directories or files at given branches or tags, the service '''commits.kde.org''' exists. It maps and forwards URLs to the respective current service URLs. | ||
The pattern for URLs to commits is this: | The pattern for URLs to commits is this: | ||
Line 467: | Line 548: | ||
https://commits.kde.org/<repo-id>[?[path=<pathToFileOrDirectory]&[branch=<branch>|tag=<tag>]] | https://commits.kde.org/<repo-id>[?[path=<pathToFileOrDirectory]&[branch=<branch>|tag=<tag>]] | ||
</pre> | </pre> | ||
<path> should be without a leading /. It defaults to the top-level directory if not set. Either a branch or tag can be passed at which the objects should be shown. It defaults to the main branch (master usually). | <path> should be without a leading /. It defaults to the top-level directory if not set. Either a branch or tag can be passed at which the objects should be shown. It defaults to the main branch (master usually). | ||
Examples: | Examples: | ||
Line 476: | Line 557: | ||
</pre> | </pre> | ||
There currently is no service to generate commit.kde.org URLs from URLs for the actual system. This has to be done manually. | There currently is no service to generate commit.kde.org URLs from URLs for the actual system. This has to be done manually. | ||
=== Creating a merge request using the command line === | === Creating a merge request using the command line === | ||
GitLab supports <code>git push</code> options that can push your branch and create a merge request in one go. For example: | |||
{{Input|1=<nowiki> | {{Input|1=<nowiki> | ||
git push -o merge_request.create -o merge_request.target=master -o merge_request.remove_source_branch -o merge_request.assign=foo | git push -o merge_request.create -o merge_request.target=master -o merge_request.remove_source_branch -o merge_request.assign=foo | ||
</nowiki>}} | </nowiki>}} | ||
replace <code>foo</code> with your actual user name. This command will push the branch, create a merge request, targeting the <code>master</code> branch, enable the "delete branch on merge" option, and assign the merge request to user <code>foo</code>. | replace <code>foo</code> with your actual user name. This command will push the branch, create a merge request, targeting the <code>master</code> branch, enable the "delete branch on merge" option, and assign the merge request to user <code>foo</code>. | ||
You can change any of those parameters to suit your usage. For more details on | You can change any of those parameters to suit your usage. For more details on GitLab push options see [https://docs.gitlab.com/ee/user/project/push_options.html this]. | ||
If you have a branch with several commits, | If you have a branch with several commits, you'll most likely still need to tweak the merge request description, etc. | ||
Of course that's a lot to type, so it's easier to use a Git alias | Of course, that's a lot to type, so it's easier to use a Git alias. For example this command will add an alias called <code>push-mr</code> to your Git config: | ||
{{Input|1=<nowiki> | {{Input|1=<nowiki> | ||
Line 497: | Line 578: | ||
</nowiki>}} | </nowiki>}} | ||
then you can use <code>git push-mr</code> like any other Git command. For more information about Git aliases see [https://git-scm.com/book/en/v2/Git-Basics-Git-Aliases this] | then you can use <code>git push-mr</code> like any other Git command. For more information about Git aliases see [https://git-scm.com/book/en/v2/Git-Basics-Git-Aliases this] | ||
=== Things to watch out for === | |||
* To avoid overloading the system, there is a '''100 commit push limit''' for merges that come from outside the target repository. This includes both branches on forks and the special <code>work/</code> branches. For large code changes, the code must be in a regular branch inside the target (main) repository. | |||
* Merge requests may sometimes fail for text files with long lines, typically SVG, JSON or XML files. If this happens, check that the master branch of the top level of the repository has ".gitattributes" file to mark these as binary files, with example content | |||
''' | |||
*.svg binary | |||
''' |
Latest revision as of 03:24, 10 December 2024
KDE uses a GitLab instance at https://invent.kde.org for code review (as well as hosting and other important collaboration tasks). This page is intended to serve as a general-purpose introduction to the most important aspects: submitting and reviewing Merge Requests.
Logging in
Navigate to https://invent.kde.org/users/sign_in and log in using the username and password for your KDE Identity account.
If you don't have an KDE Identity already you can sign up for one here. You will be required to provide a name and an email address. When selecting your username, please select something which has a relation to your real name. These details will be synced to GitLab once you have logged in and will also become your primary Git email address. You may receive some email spam as a consequence.
Setting up Git
You will need to set up git to use your account details to help identify your work. Make sure that these details match your GitLab profile, otherwise commits can't be traced back to your account.
$ git config --global user.name "Your Real Name"
$ git config --global user.email "Your identity.kde.org email"
In order to authenticate yourself when pushing code changes, you need to add a SSH key to your GitLab profile as described here.
Submitting a merge request
When making large changes to any KDE source code, we organize work into Merge Requests. They are a collection of one or many commits that you want to merge into the master branch.
Build the project from source and make your change
First you need to check out the project, compile it from source, and make some changes that you would like to submit to KDE! Instructions for doing this can be found at Get Involved/development. You will wind up with a checkout of the project at ~/kde/src/[the project name] with some local changes applied to it.
Fork the project
Once you have made some local changes that you would like to submit to KDE, you need to create a personal fork of the project and push your changes to the forked copy.
Navigate to https://invent.kde.org/explore/groups and locate the project. If it is not visible in the list, you can use the search field. Once you find the project, click on it:
On the project's page, click on the "Fork" button in the top-right corner of the screen:
This will take you to a page asking you some details about how you want to fork the project. Select Your Name in the "Project URL" section and "Public" in the "Visibility level" section:
After a moment, the system will finish creating the fork and take you to the page for your fork. On that page, click on the blue "Clone" button in the top-right corner:
In the pop-up that appears, click on the "Copy" button to the right of the upper text field. This will copy the URL for the fork onto your clipboard.
If the blue "Clone" button is missing, append .git to the URL of the current page and copy this.
Clone the repository to your local environment
git clone [the URL you copied to your clipboard]
cd [the name of the repository]
If you need to verify Invent's ssh host fingerprint, these can be found here: https://invent.kde.org/help/instance_configuration
Add the fork to your source checkout
Next, open your terminal app and navigate to the location where the project's repo lives (i.e. ~/kde/src/[the project name]).
You need to add your fork as a remote to the existing repo:
git remote add fork [the URL you copied to your clipboard]
Run "git remote -v". You should see something like this:
$ git remote -v fork [email protected]:ngraham/kid3.git (fetch) fork [email protected]:ngraham/kid3.git (push) origin https://invent.kde.org/kde/kid3.git (fetch) origin https://invent.kde.org/kde/kid3.git (push)
This means you have two remotes set up for your repo: "origin" points to the original repo, and "fork" points to your fork of it.
Make a branch and commit
Now that you have your fork set up, it's time to create a branch to track your work and make a commit.
git checkout -b my_awesome_feature git add [the files you changed] git commit
It is important to create a git branch in your git fork remote, and not use the git master branch. This is because the master git branch in the fork git remote is tracking the master git branch in origin. By not using the master branch in fork, you will be able to do git rebase.
Write a good commit message
Please follow commit message best practices: write a descriptive title in the form of an imperative sentence (e.g. "Fix button disappearing when view is changed") and on the next line, write at least one sentence describing your change and why it is necessary, and adding more details if necessary.
If your patch is intended to fix a Bugzilla ticket, include the following on its own line:
BUG: 385942
(The number should be just the Bugzilla ticket number, not the full URL)
For example a commit message might read:
Close memory leak in GC The GC was doing a bad job and leaking memory. Explicitly call delete where necessary. BUG: 385942 FIXED-IN: 5.0.0
Here is more information about other special messages that interact with Bugzilla tickets.
Push to your fork
At this point you have a branch in your local repository called "my_awesome_feature" (Hopefully, in reality, it is named something a bit more appropriate!) that has a commit on it with your work. Now push it to your fork:
git push fork my_awesome_feature
This will produce a message somewhat like this:
$ git push fork my_awesome_feature Enumerating objects: 5, done. Counting objects: 100% (5/5), done. Delta compression using up to 4 threads Compressing objects: 100% (3/3), done. Writing objects: 100% (3/3), 303 bytes | 303.00 KiB/s, done. Total 3 (delta 2), reused 0 (delta 0) remote: This commit is available for viewing at: remote: https://invent.kde.org/ngraham/kid3/commit/23a702439f494806cf3cfe14f212df58a0075bba remote: remote: To create a merge request for my_awesome_feature, visit: remote: https://invent.kde.org/ngraham/kid3/merge_requests/new?merge_request%5Bsource_branch%5D=my_awesome_feature remote: To invent.kde.org:ngraham/kid3.git * [new branch] my_awesome_feature -> my_awesome_feature
Create the merge request
Notice the "To create a merge request for my_awesome_feature..." message in the output of the push command (explained in the previous section). You can copy-and-paste the URL shown below it into a web browser. On some terminal apps, such as Konsole and Yakuake, you can ctrl+click on the link to go right there!
You will be taken to a web page that looks like this:
In the Description section, write at least one sentence describing your change and why it is necessary, adding more details if needed. Tag any of the following teams in the description text based on what kind of review you would like:
- General QA review: @teams/qa
- Visual and UI review: @teams/vdg (please add before-and-after screenshots)
- Usability review: @teams/usability
- Questions about translations: @teams/localization
If your patch is related to any existing issue or merge request on Invent, be sure to paste the link to them in the description. Connecting related issues and MRs makes them significantly easier to find, both for you and for others later on.
If your patch is intended to fix a Bugzilla ticket, include the ticket number at the bottom of the description, just like how you did in the commit message (as explained in Infrastructure/GitLab#Write_a_good_commit_message):
BUG: 385942 FIXED-IN: 5.21
Once you're done with that, click the "Submit Merge Request" button!
What happens next?
After you've submitted your Merge Request, KDE developers who work with the software in question will review it and provide feedback. This can often take a few days. However, if nobody has responded after a week, it's likely that the review was overlooked (sorry about that!) and it's appropriate to make a comment saying, "Ping!" or something to that effect.
Once the Merge Request is accepted, KDE Developers will merge it for you!
Making changes to a merge request
Oftentimes, reviewers will request changes before the Merge Request can be merged. To accomplish this you need to make the requested changes locally and then create a new commit including your changes. First, stage all changed files:
git add -u
Now make a new commit with the staged files:
git commit
Then push the local branch with the new commit on it up to the remote branch:
git push fork
Rebasing a merge request
When other changes have been made to the project's source code repo since you submitted your Merge Request, you will need to rebase the Merge Request to incorporate those changes.
Confirm that you have the origin setup correctly by issuing git remote -v
:
fork [email protected]:developer/projectfork.git (fetch) fork [email protected]:developer/projectfork.git (push) origin https://invent.kde.org/applicationgroup/originalproject.git (fetch) origin https://invent.kde.org/applicationgroup/originalproject.git (push)
It doesn't matter whether the original project is of type https://
or git@
, as you'll just fetch it.
If you instead see:
origin [email protected]:developer/projectfork.git (fetch) origin [email protected]:developer/projectfork.git (push)
You'll need to rename your origin to fork or any similar name that is easily recognizable and add the original project as your new origin:
# Rename your origin to "fork" git remote rename origin fork # Add new origin project git remote add origin https://invent.kde.org/applicationgroup/originalproject.git
Now you may proceed:
# First, make sure you are on the branch for your Merge Request git checkout mybranch # Now fetch the new changes in the repository git fetch # And finally rebase it git pull --rebase origin master
At this point there may be merge conflicts. If there are, git will tell you which files have conflicts. You can then open each file and resolve the conflict by editing the contents to keep only the appropriate change. In order to accomplish that you can either make each change manually or you can use git mergetool
which will open a diff tool of your choice (if there's any installed).
If you use a diff tool like meld, for example, the origin will be shown on the left, your fork will be shown on the right, and you may pick which changes to apply to the middle file, the new one.
After resolving the existing conflicts, run git add [file path]
on each conflicted file once all the conflicts have been resolved. Lastly, run git rebase --continue
to finish the rebase.
Now, you need to overwrite the version of the Merge Request on your remote branch with the version on your local branch. To do this, you have to force-push:
git push --force fork
Cherry-picking a merge request's git commit to another branch
If a Merge Request was labeled with the "cherry-pick" label, it should be manually cherry-picked to the branch corresponding to the target milestone after it is merged to master. To do this, click on the link to the commit that was generated:
On that page, click the "Options" button and then "Cherry-Pick" from its drop-down menu:
In the dialog that appears, select the branch you want to cherry-pick the commit to, and then click the "Cherry-Pick" button. This will create a new merge request for the change. Set it to auto-merge once the pipeline is successful. If the pipeline fails, it is your responsibility to figure out what went wrong and fix it!
You can also manually cherry-pick the commit using the git command line. When doing so, always add the -x
option to git-cherry-pick
. This is not recommended because it bypasses the CI pipeline. Making a merge request via the web UI is preferred.
Testing someone else's merge request
First you'll need to set up a development environment, if you haven't already. To do this, follow the instructions here.
Once your development environment is set up, you can use the git mr tool to check out local branches for people's merge requests so you can compile and test them. This tool lives in the Git Extras project, and is typically packaged by distros under the name "git-extras". Here's how to install it for various Linux distributions:
Arch Linux
- The git-extras package is not available in the Arch Linux repositories, only the AUR, so it needs to be built and installed with makepkg.
- For more information on using makepkg refer to its manual or Arch Linux Wiki entry.
cd /tmp git clone https://aur.archlinux.org/git-extras.git cd ./git-extras makepkg -si cd /tmp rm -rd /tmp/git-mr
Debian, Ubuntu, & KDE Neon
sudo apt install git-extras
Fedora
sudo dnf install git-extras
Manjaro
- The git-extras package is not available in the Manjaro repositories, only the AUR, so it needs to be built and installed with pamac.
pamac build git-extras
openSUSE Leap 15.5
- The git-extras package is not available in the default openSUSE 15.5 repositories but it is available in the experimental devel:tools:scm repository.
sudo zypper addrepo https://download.opensuse.org/repositories/devel:tools:scm/15.5/devel:tools:scm.repo sudo zypper refresh sudo zypper install git-extras
openSUSE Tumbleweed
- The git-extras package is not available in the default openSUSE Tumbleweed repositories but it is available in the experimental devel:tools:scm repository.
sudo zypper addrepo https://download.opensuse.org/repositories/devel:tools:scm/openSUSE_Tumbleweed/devel:tools:scm.repo sudo zypper refresh sudo zypper install git-extras
- While the git-extras package is not available in the default openSUSE Tumbleweed repositories, the git mr tool itself has been packaged standalone and is available for those that don't want or need the full git-extras package.
sudo zypper install git-mr
Check out the merge request and compile the software
First check out or enter the source repository for the software that's being patched. For example, let's say you want to test a Merge Request for Okular. If you've never built it before, check it out and build it once first:
kde-builder okular
Now go to its source directory:
cd ~/kde/src/okular
Find the Merge Request's ID. For example, for https://invent.kde.org/kde/okular/merge_requests/80, the ID is 80.
...and apply the Merge Request:
git mr 80
Now it's time to compile and run the software to make sure that the Merge Request does what it says it does and doesn't cause any regressions! Compile the patched source code:
kde-builder okular --no-src --no-include-dependencies
Those arguments will tell kde-builder to not update the source code and to not build any dependencies.
If it didn't compile, that's reason alone to reject the Merge Request! Go to the web page for the Merge Request and report your findings.
Perform QA
If it did compile, then it's time to perform QA because it's important to thoroughly test Merge Requests to ensure that bad code and regressions don't slip in. This is the entire purpose of having a review infrastructure and it is very important!
First make sure the unit tests all pass:
cd ~kde/build/kde/applications/okular source prefix.sh ctest --output-on-failure
If any tests fail, report this through a comment on the Merge Request's web page.
Next, if it's not clear how to test the Merge Request, leave a comment gently explaining this and asking for the submitter to change the Description section to describe how to test it.
Once you know how to test the Merge Request, use the software with the Merge Request applied. Test whether it crashes on launch, whether the main UI appears, and so on. If the Merge Request references any bug reports, read them, understand what issue they are reporting, and test the change to make sure it fixes the bugs.
Try to avoid reviewing parts of the software that have not been changed by the Merge Request, or proposing changes that are unrelated to the Merge Request. It's common to see a screenshot of a change and get ideas for other things that could be improved in the future, but try to avoid bringing those up in the Merge Request itself! Instead discuss those topics elsewhere later.
Next, try to break the Merge Request. Here are some ideas:
- Remove the program's configuration file (~/.config/<program name>rc) and re-open it
- Try the program with multiple HiDPI scale factors and without one at all, different font sizes, or languages known to have long text like German or Brazilian Portuguese
- If it's a new feature, feed it unexpected input
- Test related functionality
A good Merge Request will handle corner cases and variations in configuration. The price of configurability is vigilant testing! We owe it to our users to test using many configurations, not just the defaults or our personal settings.
If the result of your testing is positive because the change fixes all referenced bugs and causes no regressions, leave a comment mentioning that you performed QA and are approving on the basis of QA, and click the Approve button!
If not, apply the "Needs Changes" label and write a comment describing the issues you discovered. It is permissible to do this even if you have not been specified as a reviewer! Anyone can reject a Merge Request on the grounds that it does not work, does not do what it says it does, or causes regressions.
Perform code review
Code review is a complex topic, but anyone can learn how to do it well! Here are some resources that can help:
- https://google.github.io/eng-practices/review/reviewer/
- https://philbooth.me/blog/the-art-of-good-code-review
Engage with the author and other reviewers
After you have run the program and evaluated the Merge Request, it's time to leave some review comments on the webpage. If you have been specified as a reviewer, or are a member of a group that has been specified as a reviewer, it is permissible to Accept the Merge Request. Keep in mind that reviewing involves responsibility: you are giving a thumbs-up to code that will be run potentially by millions of people. If you accept and land a Merge Request that causes regressions, you will be expected to help fix it if the original author cannot or has disappeared. It is important to take the reviewer role seriously.
Advanced topics
Curating your merge request commit history
For large or complex merge requests, it is strongly recommended to separate the pieces of your proposed change into individual commits--one for each component of the proposed change. For example, perhaps you are working on a feature that consists of multiple logically separable elements that nonetheless all live in the same source repo, or perhaps you are first doing some code refactoring, then you add a backend feature, then finally you add a front-end user interface for it.
For this workflow, specifically mention in the merge request description that you would like reviewers to review individual commits separately, and not squash when merging.
If you need to later make changes to your Merge Request, do not add new commits; instead, combine the new changes with one of the existing commits using Git's interactive rebasing feature. To learn how to do this, see https://git-rebase.io/
Using work branches instead of forks
If you have a developer account, you don't need to use forks to submit merge requests. Instead, make sure your branch name begins with work/
and push it straight to the main repo. work/
branches are treated specially, as you can use git push --force
with them. By convention, it is recommended to add your KDE username to the branch, so the final name would end up looking like work/your-username/my-awesome-feature
.
To make it easier creating new work
branches (instead of typing work/your-username/branch-name every time), you can use a Git script to do that; for example, if you create a shell script somewhere in your PATH
, and name it e.g. git-work
(the script name must start with git-), and make the script executable:
git-work
#!/usr/bin/bash
if [ -z "$1" ]; then
echo "Cannot create a work branch with an empty name after the last /"
exit 1
fi
git checkout -b work/your-user-name/$1
you can then use:
git-work branch-name
which will create a branch called work/your-username/branch-name
that tracks origin/master
and then switches to the newly created branch.
Switching the target branch of a merge request
Sometimes you will submit a merge request that is targeting the master branch, but will later be asked to target the stable branch instead because it is a bugfix or, perhaps, you have targeted the stable branch but the commit is considered too invasive and you are asked to target the master branch instead. In either of those circumstances you will need to re-target your Merge Request. Here's how:
git checkout [the local branch for your merge request] git fetch git rebase -i origin/[the name of the remote branch you want to target; for example release/19.12]
This will open a text editor showing a list of commits, each on a separate line. Delete all of the lines of text except for the ones corresponding to new commits you have added as part of your merge request. Next, fix any merge conflicts if there are any.
Then force-push the branch up to GitLab again:
git push --force fork
Finally, edit the merge request by clicking the "Edit" button in the top-right corner of the page and choose the desired different target branch:
Note that after merging a Merge Request to the stable branch, you are expected to merge that branch back to master
afterwards:
git fetch origin git checkout release/19.12 git pull git checkout master git pull git merge -s recursive -Xours release/19.12 git diff origin/master # Are the changes what you expected? git push
Requesting exceptions to feature or string freezes
Many KDE products are affected by a feature freeze or a string freeze at various points in their development. The timing of these freezes are indicated on the product pages linked to here. Sometimes the people reviewing your merge request will tell you that an exception to one of these freezes will be required before it can be merged. To request one, send an email to the relevant mailing list:
- For a string freeze exception, email [email protected]
- For a feature freeze exception for software on the Plasma release schedule, email [email protected]
- For a feature freeze exception for software on the KDE Gear release schedule, email [email protected]
- For a feature freeze exception for anything else, email [email protected]
Here's a sample email:
Hello [translators/fellow developers!]
I'd like to request a [string/feature] freeze exception for [insert URL of your merge request]. I feel that this is important to get into the next release because [insert convincing reason here].
As I am not subscribed to this mailing list, please use "Reply All" rather than "Reply List". [can be omitted if you are in fact subscribed to the mailing list]
Thanks!
A string freeze exception is considered granted once translators from at least two teams have approved and none have disapproved.
A feature freeze exception is considered granted once two developers approve and no one has disapproved.
Pushing commits to somebody else's fork
Sometimes someone will say "Hey, let's work on my branch together," so you will be pushing commits to neither origin nor your fork, but to someone else's fork. Let's say you are asked to help work on joliveira's "gsoc2019_numberFormat" branch.
First, you would need to add the URL for his fork as a remote:
$ cd ~/kde/src/okular $ git remote add joliveira_fork [email protected]:joliveira/okular.git $ git remote -v aacid_fork [email protected]:aacid/okular.git (fetch) aacid_fork [email protected]:aacid/okular.git (push) joliveira_fork [email protected]:joliveira/okular.git (fetch) joliveira_fork [email protected]:joliveira/okular.git (push) origin https://invent.kde.org/kde/okular.git (fetch) origin https://invent.kde.org/kde/okular.git (push)
Notice how there are now multiple forks set up as remotes.
Next, you need to fetch all the repo metadata from the new remote:
git fetch joliveira_fork
This will download the list of branches. The next step is to switch to the one you want to collaborate on:
git checkout --track joliveira_fork/gsoc2019_numberFormat
This will create a local branch named "gsoc2019_numberFormat" from the contents of the remote branch joliveira_fork/gsoc2019_numberFormat and that also "tracks" it. This means that if someone else pushes changes to a remote version of that branch then you can run git pull --rebase
while on your local "gsoc2019_numberFormat" branch to bring it up to date.
Next, make your changes, add and commit. Then push the changes to the remote joliveira_fork remote:
git push joliveira_fork gsoc2019_numberFormat
Generating "eternal" URLs to commits or objects in a repository
History has taught that no system used by KDE around the code repositories stays forever. Quickgit, CGit, Phabricator & Co. came and at one point were replaced while, sadly, also taking with them their service-specific URLs (and host names).
To give documentation, blog posts, commit messages, and other long-living documents a way to reference commits or objects in the repository, like directories or files at given branches or tags, the service commits.kde.org exists. It maps and forwards URLs to the respective current service URLs.
The pattern for URLs to commits is this:
https://commits.kde.org/<repo-id>/<commit-id>
Example:
https://commits.kde.org/kcoreaddons/d2f4d353327b322ee6bfcc303169190ae44393f0
The pattern for URLs to objects is like this:
https://commits.kde.org/<repo-id>[?[path=<pathToFileOrDirectory]&[branch=<branch>|tag=<tag>]]
<path> should be without a leading /. It defaults to the top-level directory if not set. Either a branch or tag can be passed at which the objects should be shown. It defaults to the main branch (master usually).
Examples:
https://commits.kde.org/kcoreaddons?path=src # points to src/ directory in master branch https://commits.kde.org/kcoreaddons?path=README.md&tag=v5.0.0 # points to README.md file at tag v5.0.0 https://commits.kde.org/kdelibs?path=kdecore/tests&branch=KDE/3.5 # points to kdecore/tests directory in branch KDE/3.5
There currently is no service to generate commit.kde.org URLs from URLs for the actual system. This has to be done manually.
Creating a merge request using the command line
GitLab supports git push
options that can push your branch and create a merge request in one go. For example:
git push -o merge_request.create -o merge_request.target=master -o merge_request.remove_source_branch -o merge_request.assign=foo
replace foo
with your actual user name. This command will push the branch, create a merge request, targeting the master
branch, enable the "delete branch on merge" option, and assign the merge request to user foo
.
You can change any of those parameters to suit your usage. For more details on GitLab push options see this.
If you have a branch with several commits, you'll most likely still need to tweak the merge request description, etc.
Of course, that's a lot to type, so it's easier to use a Git alias. For example this command will add an alias called push-mr
to your Git config:
git config --global alias.push-mr 'push -o merge_request.create -o merge_request.target=master -o merge_request.remove_source_branch -o merge_request.assign=foo'
then you can use git push-mr
like any other Git command. For more information about Git aliases see this
Things to watch out for
- To avoid overloading the system, there is a 100 commit push limit for merges that come from outside the target repository. This includes both branches on forks and the special
work/
branches. For large code changes, the code must be in a regular branch inside the target (main) repository. - Merge requests may sometimes fail for text files with long lines, typically SVG, JSON or XML files. If this happens, check that the master branch of the top level of the repository has ".gitattributes" file to mark these as binary files, with example content
*.svg binary