snapshot of https://github.com/zulip/zulip.git @ 48c69911c7dd4e03b20552eb3bd77ad8151c1357 (2026-09-15)
Some checks failed
Code scanning / CodeQL (push) Failing after 15s
Zulip production suite / Ubuntu 22.04 production build (push) Failing after 26s
Zulip production suite / Debian 12 production install with custom db name and user (push) Has been skipped
Zulip production suite / Ubuntu 22.04 production install and PostgreSQL upgrade with pgroonga (push) Has been skipped
Zulip production suite / Ubuntu 24.04 production install (push) Has been skipped
Zulip production suite / Ubuntu 26.04 production install (push) Has been skipped
Zulip production suite / Debian 13 production install (push) Has been skipped
Zulip production suite / 7.0 Version Upgrade (push) Has been skipped
Zulip production suite / 8.0 Version Upgrade (push) Has been skipped
Zulip production suite / 6.0 Version Upgrade (push) Has been skipped
Zulip production suite / 10.0 Version Upgrade (push) Has been skipped
Zulip production suite / 9.0 Version Upgrade (push) Has been skipped
Zulip production suite / 12.0 Version Upgrade (push) Has been skipped
Zulip production suite / 11.0 Version Upgrade (push) Has been skipped
GitHub Actions Security Analysis with zizmor / zizmor (push) Failing after 3s
Zulip CI / Debian 12 (Python 3.11, backend + documentation) (push) Failing after 26s
Zulip CI / Ubuntu 22.04 (Python 3.10, backend + frontend) (push) Failing after 3s
Zulip CI / Ubuntu 24.04 (Python 3.12, backend) (push) Failing after 25s
Zulip CI / Ubuntu 26.04 (Python 3.14, backend) (push) Failing after 25s
Zulip CI / Debian 13 (Python 3.13, backend) (push) Failing after 28s
Zulip production suite / Required jobs (push) Has been cancelled
Zulip CI / Required jobs (push) Has been cancelled
API Documentation Update Check / check-feature-level-updated (push) Has been cancelled
API Documentation Update Check / notify-if-api-docs-changed (push) Has been cancelled
Some checks failed
Code scanning / CodeQL (push) Failing after 15s
Zulip production suite / Ubuntu 22.04 production build (push) Failing after 26s
Zulip production suite / Debian 12 production install with custom db name and user (push) Has been skipped
Zulip production suite / Ubuntu 22.04 production install and PostgreSQL upgrade with pgroonga (push) Has been skipped
Zulip production suite / Ubuntu 24.04 production install (push) Has been skipped
Zulip production suite / Ubuntu 26.04 production install (push) Has been skipped
Zulip production suite / Debian 13 production install (push) Has been skipped
Zulip production suite / 7.0 Version Upgrade (push) Has been skipped
Zulip production suite / 8.0 Version Upgrade (push) Has been skipped
Zulip production suite / 6.0 Version Upgrade (push) Has been skipped
Zulip production suite / 10.0 Version Upgrade (push) Has been skipped
Zulip production suite / 9.0 Version Upgrade (push) Has been skipped
Zulip production suite / 12.0 Version Upgrade (push) Has been skipped
Zulip production suite / 11.0 Version Upgrade (push) Has been skipped
GitHub Actions Security Analysis with zizmor / zizmor (push) Failing after 3s
Zulip CI / Debian 12 (Python 3.11, backend + documentation) (push) Failing after 26s
Zulip CI / Ubuntu 22.04 (Python 3.10, backend + frontend) (push) Failing after 3s
Zulip CI / Ubuntu 24.04 (Python 3.12, backend) (push) Failing after 25s
Zulip CI / Ubuntu 26.04 (Python 3.14, backend) (push) Failing after 25s
Zulip CI / Debian 13 (Python 3.13, backend) (push) Failing after 28s
Zulip production suite / Required jobs (push) Has been cancelled
Zulip CI / Required jobs (push) Has been cancelled
API Documentation Update Check / check-feature-level-updated (push) Has been cancelled
API Documentation Update Check / notify-if-api-docs-changed (push) Has been cancelled
This commit is contained in:
118
docs/git/cheat-sheet.md
Normal file
118
docs/git/cheat-sheet.md
Normal file
@@ -0,0 +1,118 @@
|
||||
# Git cheat sheet
|
||||
|
||||
See also [fixing commits][fix-commit]
|
||||
|
||||
## Common commands
|
||||
|
||||
- add
|
||||
- `git add foo.py`
|
||||
- checkout
|
||||
- `git checkout -b new-branch-name`
|
||||
- `git checkout main`
|
||||
- `git checkout old-branch-name`
|
||||
- commit
|
||||
- `git commit -m "topic: Commit message title."`
|
||||
- `git commit --amend`: Modify the previous commit.
|
||||
- config
|
||||
- `git config --global core.editor nano`
|
||||
- `git config --global core.symlinks true`
|
||||
- diff
|
||||
- `git diff`
|
||||
- `git diff --cached`
|
||||
- `git diff HEAD~2..`
|
||||
- fetch
|
||||
- `git fetch origin`
|
||||
- `git fetch upstream`
|
||||
- grep
|
||||
- `git grep update_unread_counts`
|
||||
- log
|
||||
- `git log`
|
||||
- pull
|
||||
- `git pull --rebase`: **Use this**. Zulip uses a [rebase oriented workflow][git-overview].
|
||||
- `git pull` (with no options): Will either create a merge commit
|
||||
(which you don't want) or do the same thing as `git pull --rebase`,
|
||||
depending on [whether you've configured Git properly][git-config-clone]
|
||||
- push
|
||||
- `git push origin +branch-name`
|
||||
- rebase
|
||||
- `git rebase -i HEAD~3`
|
||||
- `git rebase -i main`
|
||||
- `git rebase upstream/main`
|
||||
- reflog
|
||||
- `git reflog | head -10`
|
||||
- remote
|
||||
- `git remote -v`
|
||||
- reset
|
||||
- `git reset HEAD~2`
|
||||
- rm
|
||||
- `git rm oops.txt`
|
||||
- show
|
||||
- `git show HEAD`
|
||||
- `git show HEAD~~~`
|
||||
- `git show main`
|
||||
- status
|
||||
- `git status`
|
||||
|
||||
## Detailed cheat sheet
|
||||
|
||||
- add
|
||||
- `git add foo.py`: add `foo.py` to the staging area
|
||||
- `git add foo.py bar.py`: add `foo.py` AND `bar.py` to the staging area
|
||||
- `git add -u`: Adds all tracked files to the staging area.
|
||||
- checkout
|
||||
- `git checkout -b new-branch-name`: create branch `new-branch-name` and switch to/check out that new branch
|
||||
- `git checkout main`: switch to your `main` branch
|
||||
- `git checkout old-branch-name`: switch to an existing branch `old-branch-name`
|
||||
- commit
|
||||
- `git commit -m "commit message"`: It is recommended to type a
|
||||
multiline commit message, however.
|
||||
- `git commit`: Opens your default text editor to write a commit message.
|
||||
- `git commit --amend`: changing the last commit message. Read more [here][fix-commit]
|
||||
- config
|
||||
- `git config --global core.editor nano`: set core editor to `nano` (you can set this to `vim` or others)
|
||||
- `git config --global core.symlinks true`: allow symbolic links
|
||||
- diff
|
||||
- `git diff`: display the changes you have made to all files
|
||||
- `git diff --cached`: display the changes you have made to staged files
|
||||
- `git diff HEAD~2..`: display the 2 most recent changes you have made to files
|
||||
- fetch
|
||||
- `git fetch origin`: fetch origin repository
|
||||
- `git fetch upstream`: fetch upstream repository
|
||||
- grep
|
||||
- `git grep update_unread_counts web/src`: Search our JS for references to update_unread_counts.
|
||||
- log
|
||||
- `git log`: show commit logs
|
||||
- `git log --oneline | head`: To quickly see the latest ten commits on a branch.
|
||||
- `git log -p`: show commit logs with changes; see [the "secret" to reading it's output][git-log-secret]
|
||||
- pull
|
||||
- `git pull --rebase`: rebase your changes on top of `main`.
|
||||
- `git pull` (with no options): Will either create a merge commit
|
||||
(which you don't want) or do the same thing as `git pull --rebase`,
|
||||
depending on [whether you've configured Git properly][git-config-clone]
|
||||
- push
|
||||
- `git push origin branch-name`: push you commits to the origin repository _only if_ there are no conflicts.
|
||||
Use this when collaborating with others to prevent overwriting their work.
|
||||
- `git push origin +branch-name`: force push your commits to your origin repository.
|
||||
- rebase
|
||||
- `git rebase -i HEAD~3`: interactive rebasing current branch with first three items on HEAD
|
||||
- `git rebase -i main`: interactive rebasing current branch with `main` branch
|
||||
- `git rebase upstream/main`: rebasing current branch with `main` branch from upstream repository
|
||||
- reflog
|
||||
- `git reflog | head -10`: manage reference logs for the past 10 commits
|
||||
- remote
|
||||
- `git remote -v`: display your origin and upstream repositories
|
||||
- reset
|
||||
- `git reset HEAD~2`: reset two most recent commits
|
||||
- rm
|
||||
- `git rm oops.txt`: remove `oops.txt`
|
||||
- show
|
||||
- `git show HEAD`: display most recent commit
|
||||
- `git show HEAD~~~`: display third most recent commit
|
||||
- `git show main`: display most recent commit on `main`
|
||||
- status
|
||||
- `git status`: show the working tree status, unstaged and staged files
|
||||
|
||||
[fix-commit]: fixing-commits.md
|
||||
[git-log-secret]: reading-history.md#the-secret-to-using-git-log--p
|
||||
[git-config-clone]: cloning.md#step-1b-clone-to-your-machine
|
||||
[git-overview]: overview.md
|
||||
140
docs/git/cloning.md
Normal file
140
docs/git/cloning.md
Normal file
@@ -0,0 +1,140 @@
|
||||
# Get Zulip code
|
||||
|
||||
Zulip uses a **forked-repo** and **[rebase][gitbook-rebase]-oriented
|
||||
workflow**. This means that all contributors create a fork of the [Zulip
|
||||
repository][github-zulip] they want to contribute to and then submit pull
|
||||
requests to the upstream repository to have their contributions reviewed and
|
||||
accepted. We also recommend you work on feature branches.
|
||||
|
||||
## Step 1a: Create your fork
|
||||
|
||||
The following steps you'll only need to do the first time you set up a machine
|
||||
for contributing to a given Zulip project. You'll need to repeat the steps for
|
||||
any additional Zulip projects ([list][github-zulip]) that you work on.
|
||||
|
||||
The first thing you'll want to do to contribute to Zulip is fork ([see
|
||||
how][github-help-fork]) the appropriate [Zulip repository][github-zulip]. For
|
||||
the main server app, this is [zulip/zulip][github-zulip-zulip].
|
||||
|
||||
## Step 1b: Clone to your machine
|
||||
|
||||
Next, clone your fork to your local machine:
|
||||
|
||||
```console
|
||||
$ git clone --config pull.rebase https://github.com/YOUR_USERNAME/zulip.git
|
||||
Cloning into 'zulip'
|
||||
remote: Counting objects: 86768, done.
|
||||
remote: Compressing objects: 100% (15/15), done.
|
||||
remote: Total 86768 (delta 5), reused 1 (delta 1), pack-reused 86752
|
||||
Receiving objects: 100% (86768/86768), 112.96 MiB | 523.00 KiB/s, done.
|
||||
Resolving deltas: 100% (61106/61106), done.
|
||||
Checking connectivity... done.
|
||||
```
|
||||
|
||||
(The `--config pull.rebase` option configures Git so that `git pull`
|
||||
will behave like `git pull --rebase` by default. Using
|
||||
`git pull --rebase` to update your changes to resolve merge conflicts
|
||||
is expected by essentially all of open source projects, including
|
||||
Zulip. You can also set that option after cloning using
|
||||
`git config --add pull.rebase true`, or just be careful to always run
|
||||
`git pull --rebase`, never `git pull`).
|
||||
|
||||
Note: If you receive an error while cloning, you may not have [added your ssh
|
||||
key to GitHub][github-help-add-ssh-key].
|
||||
|
||||
Once the repository is cloned, we recommend running
|
||||
[setup-git-repo][zulip-rtd-tools-setup] to install Zulip's pre-commit
|
||||
hook which runs the Zulip linters on the changed files when you
|
||||
commit.
|
||||
|
||||
## Step 1c: Connect your fork to Zulip upstream
|
||||
|
||||
Next you'll want to [configure an upstream remote
|
||||
repository][github-help-conf-remote] for your fork of Zulip. This will allow
|
||||
you to [sync changes][github-help-sync-fork] from the main project back into
|
||||
your fork.
|
||||
|
||||
First, show the currently configured remote repository:
|
||||
|
||||
```console
|
||||
$ git remote -v
|
||||
origin git@github.com:YOUR_USERNAME/zulip.git (fetch)
|
||||
origin git@github.com:YOUR_USERNAME/zulip.git (push)
|
||||
```
|
||||
|
||||
Note: If you've cloned the repository using a graphical client, you may already
|
||||
have the upstream remote repository configured. For example, when you clone
|
||||
[zulip/zulip][github-zulip-zulip] with the GitHub desktop client it configures
|
||||
the remote repository `zulip` and you see the following output from
|
||||
`git remote -v`:
|
||||
|
||||
```console
|
||||
origin git@github.com:YOUR_USERNAME/zulip.git (fetch)
|
||||
origin git@github.com:YOUR_USERNAME/zulip.git (push)
|
||||
zulip https://github.com/zulip/zulip.git (fetch)
|
||||
zulip https://github.com/zulip/zulip.git (push)
|
||||
```
|
||||
|
||||
If your client hasn't automatically configured a remote for zulip/zulip, you'll
|
||||
need to with:
|
||||
|
||||
```console
|
||||
$ git remote add -f upstream https://github.com/zulip/zulip.git
|
||||
```
|
||||
|
||||
Finally, confirm that the new remote repository, upstream, has been configured:
|
||||
|
||||
```console
|
||||
$ git remote -v
|
||||
origin git@github.com:YOUR_USERNAME/zulip.git (fetch)
|
||||
origin git@github.com:YOUR_USERNAME/zulip.git (push)
|
||||
upstream https://github.com/zulip/zulip.git (fetch)
|
||||
upstream https://github.com/zulip/zulip.git (push)
|
||||
```
|
||||
|
||||
## Step 2: Set up the Zulip development environment
|
||||
|
||||
If you haven't already, now is a good time to install the Zulip development environment
|
||||
([overview][zulip-rtd-dev-overview]). If you're new to working on Zulip or open
|
||||
source projects in general, we recommend following our [detailed guide for
|
||||
first-time contributors][zulip-rtd-dev-first-time].
|
||||
|
||||
## Step 3: Configure continuous integration for your fork
|
||||
|
||||
This step is optional, but recommended.
|
||||
|
||||
The Zulip Server project is configured to use [GitHub Actions][github-actions]
|
||||
to test and create builds upon each new commit and pull request.
|
||||
GitHub Actions is the primary CI that runs frontend and backend
|
||||
tests across a wide range of Ubuntu distributions.
|
||||
|
||||
GitHub Actions is free for open source projects and it's easy to
|
||||
configure for your own fork of Zulip. After doing so, GitHub Actions
|
||||
will run tests for new refs you push to GitHub and email you the outcome
|
||||
(you can also view the results in the web interface).
|
||||
|
||||
Running CI against your fork can help save both your and the
|
||||
Zulip maintainers time by making it easy to test a change fully before
|
||||
submitting a pull request. We generally recommend a workflow where as
|
||||
you make changes, you use a fast edit-refresh cycle running individual
|
||||
tests locally until your changes work. But then once you've gotten
|
||||
the tests you'd expect to be relevant to your changes working, push a
|
||||
branch to run the full test suite in GitHub Actions before
|
||||
you create a pull request. While you wait for GitHub Actions jobs
|
||||
to run, you can start working on your next task. When the tests finish,
|
||||
you can create a pull request that you already know passes the tests.
|
||||
|
||||
GitHub Actions will run all the jobs by default on your forked repository.
|
||||
You can check the `Actions` tab of your repository to see the builds.
|
||||
|
||||
[gitbook-rebase]: https://git-scm.com/book/en/v2/Git-Branching-Rebasing
|
||||
[github-help-add-ssh-key]: https://help.github.com/en/articles/adding-a-new-ssh-key-to-your-github-account
|
||||
[github-help-conf-remote]: https://help.github.com/en/articles/configuring-a-remote-for-a-fork
|
||||
[github-help-fork]: https://help.github.com/en/articles/fork-a-repo
|
||||
[github-help-sync-fork]: https://help.github.com/en/articles/syncing-a-fork
|
||||
[github-zulip]: https://github.com/zulip/
|
||||
[github-zulip-zulip]: https://github.com/zulip/zulip/
|
||||
[github-actions]: https://docs.github.com/en/actions
|
||||
[zulip-rtd-dev-first-time]: ../development/setup-recommended.md
|
||||
[zulip-rtd-dev-overview]: ../development/overview.md
|
||||
[zulip-rtd-tools-setup]: zulip-tools.md#set-up-git-repo-script
|
||||
59
docs/git/collaborate.md
Normal file
59
docs/git/collaborate.md
Normal file
@@ -0,0 +1,59 @@
|
||||
# Collaborate
|
||||
|
||||
## Fetch another contributor's branch
|
||||
|
||||
What happens when you would like to collaborate with another contributor and
|
||||
they have work-in-progress on their own fork of Zulip? No problem! Just add
|
||||
their fork as a remote and pull their changes.
|
||||
|
||||
```console
|
||||
$ git remote add <username> https://github.com/<username>/zulip.git
|
||||
$ git fetch <username>
|
||||
```
|
||||
|
||||
Now you can check out their branch just like you would any other. You can name
|
||||
the branch anything you want, but using both the username and branch name will
|
||||
help you keep things organized.
|
||||
|
||||
```console
|
||||
$ git checkout -b <username>/<branchname>
|
||||
```
|
||||
|
||||
You can choose to rename the branch if you prefer:
|
||||
|
||||
```bash
|
||||
git checkout -b <custombranchname> <username>/<branchname>
|
||||
```
|
||||
|
||||
## Check out a pull request locally
|
||||
|
||||
Just as you can check out any user's branch locally, you can also check out any
|
||||
pull request locally. GitHub provides a special syntax
|
||||
([details][github-help-co-pr-locally]) for this since pull requests are
|
||||
specific to GitHub rather than Git.
|
||||
|
||||
First, fetch and create a branch for the pull request, replacing _ID_ and
|
||||
_BRANCHNAME_ with the ID of the pull request and your desired branch name:
|
||||
|
||||
```console
|
||||
$ git fetch upstream pull/ID/head:BRANCHNAME
|
||||
```
|
||||
|
||||
Now switch to the branch:
|
||||
|
||||
```console
|
||||
$ git checkout BRANCHNAME
|
||||
```
|
||||
|
||||
Now you work on this branch as you would any other.
|
||||
|
||||
Note: you can use the scripts provided in the tools/ directory to fetch pull
|
||||
requests. You can read more about what they do [here][tools-pr].
|
||||
|
||||
```bash
|
||||
tools/fetch-rebase-pull-request <PR-number>
|
||||
tools/fetch-pull-request <PR-number>
|
||||
```
|
||||
|
||||
[github-help-co-pr-locally]: https://help.github.com/en/articles/checking-out-pull-requests-locally
|
||||
[tools-pr]: zulip-tools.md#fetch-a-pull-request-and-rebase
|
||||
45
docs/git/fixing-commits.md
Normal file
45
docs/git/fixing-commits.md
Normal file
@@ -0,0 +1,45 @@
|
||||
# Fixing commits
|
||||
|
||||
This is mostly from
|
||||
[here](https://help.github.com/en/articles/changing-a-commit-message#rewriting-the-most-recent-commit-message).
|
||||
|
||||
## Fixing the last commit
|
||||
|
||||
### Changing the last commit message
|
||||
|
||||
1. `git commit --amend -m "New message"`
|
||||
|
||||
### Changing the last commit
|
||||
|
||||
1. Make your changes to the files
|
||||
2. Run `git add <filename>` to add one file or `git add <filename1> <filename2> ...` to add multiple files
|
||||
3. `git commit --amend`
|
||||
|
||||
## Fixing older commits
|
||||
|
||||
### Changing commit messages
|
||||
|
||||
1. `git rebase -i HEAD~5` (if, for example, you are editing some of the last five commits)
|
||||
2. For each commit that you want to change the message, change `pick` to `reword`, and save
|
||||
3. Change the commit messages
|
||||
|
||||
### Deleting old commits
|
||||
|
||||
1. `git rebase -i HEAD~n` where `n` is the number of commits you are looking at
|
||||
2. For each commit that you want to delete, change `pick` to `drop`, and save
|
||||
|
||||
## Squashing commits
|
||||
|
||||
Sometimes, you want to make one commit out of a bunch of commits. To do this,
|
||||
|
||||
1. `git rebase -i HEAD~n` where `n` is the number of commits you are interested in
|
||||
2. Change `pick` to `squash` on the lines containing the commits you want to squash and save
|
||||
|
||||
## Reordering commits
|
||||
|
||||
1. `git rebase -i HEAD~n` where `n` is the number of commits you are interested in
|
||||
2. Reorder the lines containing the commits and save
|
||||
|
||||
## Pushing commits after tidying them
|
||||
|
||||
1. `git push origin +my-feature-branch` (Note the `+` there and substitute your actual branch name.)
|
||||
23
docs/git/index.md
Normal file
23
docs/git/index.md
Normal file
@@ -0,0 +1,23 @@
|
||||
# Git guide
|
||||
|
||||
```{toctree}
|
||||
---
|
||||
maxdepth: 3
|
||||
---
|
||||
|
||||
Quick start <overview>
|
||||
Set up Git <setup>
|
||||
Zulip-specific tools <zulip-tools>
|
||||
How Git is different <the-git-difference>
|
||||
Important Git terms <terminology>
|
||||
Get Zulip code <cloning>
|
||||
Working copies <working-copies>
|
||||
Using Git as you work <using>
|
||||
Pull requests <pull-requests>
|
||||
Collaborate <collaborate>
|
||||
Fixing commits <fixing-commits>
|
||||
Reviewing changes <reviewing>
|
||||
Reading history <reading-history>
|
||||
Get and stay out of trouble <troubleshooting>
|
||||
Git cheat sheet <cheat-sheet>
|
||||
```
|
||||
73
docs/git/overview.md
Normal file
73
docs/git/overview.md
Normal file
@@ -0,0 +1,73 @@
|
||||
# Quick start: how Zulip uses Git and GitHub
|
||||
|
||||
This quick start provides a brief overview of how Zulip uses Git and GitHub.
|
||||
|
||||
Those who are familiar with Git and GitHub should be able to start contributing
|
||||
with these details in mind:
|
||||
|
||||
- We use **GitHub for source control and code review.** To contribute, fork
|
||||
[zulip/zulip][github-zulip-zulip] (or the appropriate
|
||||
[repository][github-zulip], if you are working on something else besides
|
||||
Zulip server) to your own account and then create feature/issue branches.
|
||||
When you're ready to get feedback, submit a [draft][github-help-draft-pr]
|
||||
pull request. _We encourage you to submit draft pull requests early and
|
||||
often._
|
||||
|
||||
- We use a **[rebase][gitbook-rebase]-oriented workflow.** We do not use merge
|
||||
commits. This means you should use `git fetch` followed by `git rebase`
|
||||
rather than `git pull` (or you can use `git pull --rebase`). Also, to prevent
|
||||
pull requests from becoming out of date with the main line of development,
|
||||
you should rebase your feature branch prior to submitting a pull request, and
|
||||
as needed thereafter. If you're unfamiliar with how to rebase a pull request,
|
||||
[read this excellent guide][edx-howto-rebase-pr].
|
||||
|
||||
We use this strategy in order to avoid the extra commits that appear
|
||||
when another branch is merged, that clutter the commit history (it's
|
||||
popular with other large projects such as Django). This makes
|
||||
Zulip's commit history more readable, but a side effect is that many
|
||||
pull requests we merge will be reported by GitHub's UI as _closed_
|
||||
instead of _merged_, since GitHub has poor support for
|
||||
rebase-oriented workflows.
|
||||
|
||||
- We have a **[code style guide][zulip-rtd-code-style]**, a **[commit message
|
||||
guide][zulip-rtd-commit-messages]**, and strive for each commit to be _a
|
||||
minimal coherent idea_ (see **[commit
|
||||
discipline][zulip-rtd-commit-discipline]** for details).
|
||||
|
||||
- We provide **many tools to help you submit quality code.** These include
|
||||
[linters][zulip-rtd-lint-tools], [tests][zulip-rtd-testing], [continuous
|
||||
integration][continuous-integration] and [mypy][zulip-rtd-mypy].
|
||||
|
||||
- We use [zulipbot][zulip-rtd-zulipbot-usage] to manage our issues and
|
||||
pull requests to create a better GitHub workflow for contributors.
|
||||
|
||||
- We provide some handy **[Zulip-specific Git scripts][zulip-rtd-zulip-tools]**
|
||||
for developers to easily do tasks like fetching and rebasing a pull
|
||||
request, cleaning unimportant branches, etc. These reduce the common
|
||||
tasks of testing other contributors' pull requests to single commands.
|
||||
|
||||
Finally, install the [Zulip developer environment][zulip-rtd-dev-overview], and then
|
||||
[configure continuous integration for your fork][zulip-git-guide-fork-ci].
|
||||
|
||||
---
|
||||
|
||||
The following sections will help you be awesome with Zulip and Git/GitHub in a
|
||||
rebased-based workflow. Read through it if you're new to Git, to a rebase-based
|
||||
Git workflow, or if you'd like a Git refresher.
|
||||
|
||||
[github-help-draft-pr]: https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/about-pull-requests#draft-pull-requests
|
||||
[gitbook-rebase]: https://git-scm.com/book/en/v2/Git-Branching-Rebasing
|
||||
[edx-howto-rebase-pr]: https://web.archive.org/web/20240204225038/https://github.com/openedx/edx-platform/wiki/How-to-Rebase-a-Pull-Request
|
||||
[github-zulip]: https://github.com/zulip/
|
||||
[github-zulip-zulip]: https://github.com/zulip/zulip/
|
||||
[continuous-integration]: ../testing/continuous-integration.md
|
||||
[zulip-git-guide-fork-ci]: cloning.md#step-3-configure-continuous-integration-for-your-fork
|
||||
[zulip-rtd-code-style]: ../contributing/code-style.md
|
||||
[zulip-rtd-commit-discipline]: ../contributing/commit-discipline.md
|
||||
[zulip-rtd-commit-messages]: ../contributing/commit-discipline.md
|
||||
[zulip-rtd-dev-overview]: ../development/overview.md
|
||||
[zulip-rtd-lint-tools]: ../contributing/code-style.md#use-the-linters
|
||||
[zulip-rtd-mypy]: ../testing/mypy.md
|
||||
[zulip-rtd-testing]: ../testing/testing.md
|
||||
[zulip-rtd-zulip-tools]: zulip-tools.md
|
||||
[zulip-rtd-zulipbot-usage]: ../contributing/zulipbot-usage.md
|
||||
163
docs/git/pull-requests.md
Normal file
163
docs/git/pull-requests.md
Normal file
@@ -0,0 +1,163 @@
|
||||
# Pull requests
|
||||
|
||||
When you're ready for feedback, submit a pull request. Pull requests
|
||||
are a feature specific to GitHub. They provide a simple, web-based way
|
||||
to submit your work (often called "patches") to a project. It's called
|
||||
a _pull request_ because you're asking the project to _pull changes_
|
||||
from your fork.
|
||||
|
||||
If you're unfamiliar with how to create a pull request, you can check
|
||||
out GitHub's documentation on
|
||||
[creating a pull request from a fork][github-help-create-pr-fork]. You
|
||||
might also find GitHub's article
|
||||
[about pull requests][github-help-about-pr] helpful. That all said,
|
||||
the tutorial below will walk you through the process.
|
||||
|
||||
## Draft pull requests
|
||||
|
||||
In the Zulip project, we encourage submitting [draft pull
|
||||
requests][github-help-draft-pr] early and often. This allows you to
|
||||
share your code to make it easier to get feedback and help with your
|
||||
changes, even if you don't think your pull request is ready to be
|
||||
merged (e.g., it might not work or pass tests). This sets expectations
|
||||
correctly for any feedback from other developers, and prevents your
|
||||
work from being merged before you're confident in it.
|
||||
|
||||
## Create a pull request
|
||||
|
||||
### Step 0: Make sure you're on a feature branch (not `main`)
|
||||
|
||||
It is important to [work on a feature
|
||||
branch](using.md#work-on-a-feature-branch) when creating a pull
|
||||
request. Your new pull request will be inextricably linked with your
|
||||
branch while it is open, so you will need to reserve your branch only
|
||||
for changes related to your issue, and avoid introducing extraneous
|
||||
changes for other issues or from upstream.
|
||||
|
||||
If you are working on a branch named `main`, you need to create and
|
||||
switch to a feature branch before proceeding.
|
||||
|
||||
### Step 1: Update your branch with git rebase
|
||||
|
||||
The best way to update your branch is with `git fetch` and `git rebase`. Do not
|
||||
use `git pull` or `git merge` as this will create merge commits. See [keep your
|
||||
fork up to date][keep-up-to-date] for details.
|
||||
|
||||
Here's an example (you would replace _issue-123_ with the name of your feature branch):
|
||||
|
||||
```console
|
||||
$ git checkout issue-123
|
||||
Switched to branch 'issue-123'
|
||||
|
||||
$ git fetch upstream
|
||||
remote: Counting objects: 69, done.
|
||||
remote: Compressing objects: 100% (23/23), done.
|
||||
remote: Total 69 (delta 49), reused 39 (delta 39), pack-reused 7
|
||||
Unpacking objects: 100% (69/69), done.
|
||||
From https://github.com/zulip/zulip
|
||||
69fa600..43e21f6 main -> upstream/main
|
||||
|
||||
$ git rebase upstream/main
|
||||
|
||||
First, rewinding head to replay your work on top of it...
|
||||
Applying: troubleshooting tip about provisioning
|
||||
```
|
||||
|
||||
### Step 2: Push your updated branch to your remote fork
|
||||
|
||||
Once you've updated your local feature branch, push the changes to GitHub:
|
||||
|
||||
```console
|
||||
$ git push origin issue-123
|
||||
Counting objects: 6, done.
|
||||
Delta compression using up to 4 threads.
|
||||
Compressing objects: 100% (4/4), done.
|
||||
Writing objects: 100% (6/6), 658 bytes | 0 bytes/s, done.
|
||||
Total 6 (delta 3), reused 0 (delta 0)
|
||||
remote: Resolving deltas: 100% (3/3), completed with 1 local objects.
|
||||
To git@github.com:christi3k/zulip.git
|
||||
+ 2d49e2d...bfb2433 issue-123 -> issue-123
|
||||
```
|
||||
|
||||
If your push is rejected with error **failed to push some refs** then you need
|
||||
to prefix the name of your branch with a `+`:
|
||||
|
||||
```console
|
||||
$ git push origin +issue-123
|
||||
Counting objects: 6, done.
|
||||
Delta compression using up to 4 threads.
|
||||
Compressing objects: 100% (4/4), done.
|
||||
Writing objects: 100% (6/6), 658 bytes | 0 bytes/s, done.
|
||||
Total 6 (delta 3), reused 0 (delta 0)
|
||||
remote: Resolving deltas: 100% (3/3), completed with 1 local objects.
|
||||
To git@github.com:christi3k/zulip.git
|
||||
+ 2d49e2d...bfb2433 issue-123 -> issue-123 (forced update)
|
||||
```
|
||||
|
||||
This is perfectly okay to do on your own feature branches, especially if you're
|
||||
the only one making changes to the branch. If others are working along with
|
||||
you, they might run into complications when they retrieve your changes because
|
||||
anyone who has based their changes off a branch you rebase will have to do a
|
||||
complicated rebase.
|
||||
|
||||
### Step 3: Open the pull request
|
||||
|
||||
If you've never created a pull request or need a refresher, take a look at
|
||||
GitHub's article on [creating a pull request from a
|
||||
fork][github-help-create-pr-fork]. We'll briefly review the process here.
|
||||
|
||||
First, sign in to GitHub on your web browser and navigate to your fork of Zulip.
|
||||
|
||||
Next, navigate to the branch you've been working on. Do this by clicking on the
|
||||
**Branch** button and selecting the relevant branch. Finally, click the **New
|
||||
pull request** button. Alternatively, if you've recently pushed the relevant
|
||||
branch to your fork, you will see a **Compare & pull request** button.
|
||||
|
||||
A pull request template will open with some information pre-filled in.
|
||||
Provide (or update) the title for your pull request and write a first comment.
|
||||
|
||||
If your pull request makes UI changes, always include one or more still
|
||||
screenshots to demonstrate your changes. If it seems helpful, add a brief
|
||||
video of the new functionality as well. Take time to read our
|
||||
[comprehensive guide to capturing screenshots](../contributing/presenting-visual-changes.md),
|
||||
which includes [a list of screenshot tools][screenshots-gifs] you can use.
|
||||
|
||||
See the documentation for creating [reviewable pull requests][reviewable-prs]
|
||||
for more guidance and tips when writing pull request comments. If the repository
|
||||
has a self-review checklist in the pull request template, make sure that all the
|
||||
relevant points have been addressed before submitting it.
|
||||
|
||||
When ready, click the **Create pull request** button to submit the pull request.
|
||||
Remember to mark your pull request as a [draft][github-help-draft-pr] if it is a
|
||||
work-in-progress.
|
||||
|
||||
Note: **Pull request titles are different from commit messages.** Commit
|
||||
messages can be edited with `git commit --amend`, `git rebase -i`, etc., while
|
||||
the title of a pull request can only be edited via GitHub.
|
||||
|
||||
## Update a pull request
|
||||
|
||||
As you get make progress on your feature or bugfix, your pull request, once
|
||||
submitted, will be updated each time you [push commits][self-push-commits] to
|
||||
your remote branch. This means you can keep your pull request open as long as
|
||||
you need, rather than closing and opening new ones for the same feature or
|
||||
bugfix.
|
||||
|
||||
It's a good idea to keep your pull request mergeable with Zulip upstream by
|
||||
frequently fetching, rebasing, and pushing changes. See [keep your fork up to
|
||||
date][keep-up-to-date] for details. You might also find this excellent
|
||||
article [How to Rebase a Pull Request][edx-howto-rebase-pr] helpful.
|
||||
|
||||
And, as you address review comments others have made, we recommend posting a
|
||||
follow-up comment in which you: a) ask for any clarifications you need, b)
|
||||
explain to the reviewer how you solved any problems they mentioned, and c) ask
|
||||
for another review.
|
||||
|
||||
[edx-howto-rebase-pr]: https://web.archive.org/web/20240204225038/https://github.com/openedx/edx-platform/wiki/How-to-Rebase-a-Pull-Request
|
||||
[github-help-about-pr]: https://help.github.com/en/articles/about-pull-requests
|
||||
[github-help-create-pr-fork]: https://help.github.com/en/articles/creating-a-pull-request-from-a-fork
|
||||
[github-help-draft-pr]: https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/about-pull-requests#draft-pull-requests
|
||||
[keep-up-to-date]: using.md#keep-your-fork-up-to-date
|
||||
[self-push-commits]: using.md#push-your-commits-to-github
|
||||
[screenshots-gifs]: ../contributing/presenting-visual-changes.md#screenshot-and-gif-software
|
||||
[reviewable-prs]: ../contributing/reviewable-prs.md
|
||||
88
docs/git/reading-history.md
Normal file
88
docs/git/reading-history.md
Normal file
@@ -0,0 +1,88 @@
|
||||
# Reading history
|
||||
|
||||
One of the things that makes Git so valuable is its facilities for
|
||||
studying history -- both
|
||||
|
||||
- very recent history (e.g., rereading your own branch before you
|
||||
send a PR), and
|
||||
- the distant past (e.g., tracking down when and why some piece
|
||||
of code became the way it is.)
|
||||
|
||||
This guide, written by Greg Price, will help you take advantage of
|
||||
these powerful abilities.
|
||||
|
||||
## Use a graphical client
|
||||
|
||||
One great way to read history: [use a graphical Git client](setup.md#get-a-graphical-client)!
|
||||
Especially helpful for
|
||||
|
||||
- reading through the recent commits, or
|
||||
- clarifying how branches are related to each other.
|
||||
|
||||
## The "secret" to using `git log -p`
|
||||
|
||||
Use `git log -p`, with this important secret:
|
||||
|
||||
- In the pager that `git log` puts you into, hit `/` to search, then enter
|
||||
the pattern `^c` -- that is, caret, then `c`. Then hit `n`/`N` for
|
||||
next/previous match.
|
||||
|
||||
- This finds lines that begin with `c`. Because of thoughtful design in
|
||||
the default format of `git log`, these are exactly the first line of the
|
||||
log entry for each commit. So with this search pattern, you effectively
|
||||
get **keybindings for "next/previous commit"**. This makes a huge
|
||||
difference in skimming quickly past boring commits without missing
|
||||
anything.
|
||||
|
||||
- For a further upgrade, use `git log --stat -p` (you might alias this as
|
||||
e.g., `git lsp`.) Now every time you hit `n` or `N`, you see the commit
|
||||
message and complete list of affected files for the new commit -- a good
|
||||
summary to help decide whether to read in more detail or hit `n`/`N`
|
||||
again to move on.
|
||||
|
||||
## Filter `git log` down to relevant commits
|
||||
|
||||
Use some of `git log`'s many features to filter down to commits you
|
||||
care about. For example:
|
||||
|
||||
- Filter to a range of commits with `git log A..B`. E.g., to reread your
|
||||
current branch relative to upstream main, you might say
|
||||
`git log --stat -p upstream/main..`, or `git log --stat -p @{u}..`.
|
||||
(Greg has the latter aliased as `git usp`, and types it constantly.)
|
||||
|
||||
- Filter to changes touching certain files or directories:
|
||||
`git log PATHS`.
|
||||
|
||||
- Filter to changes touching lines that mention some pattern:
|
||||
`git log -G PATTERN`.
|
||||
|
||||
- Filter to changes adding or removing mentions of some pattern:
|
||||
`git log -S PATTERN`. This feature is traditionally called the
|
||||
"pickaxe", presumably in honor of its power to mine just the right bit
|
||||
of historical/explanatory gold.
|
||||
|
||||
- Many more. Do take a few minutes to skim through the documentation in
|
||||
`git help log` (or [this web version](https://git-scm.com/docs/git-log))
|
||||
to get an idea of what's available; and perhaps an hour now and then to
|
||||
read and try things in more detail.
|
||||
|
||||
## Filter in your graphical client
|
||||
|
||||
Try all those `git log` filtering features in your graphical client -- it
|
||||
may even support the very same command-line options to do it. For
|
||||
example, `gitk upstream/main..` shows basically the same information as
|
||||
`git log --stat -p upstream/main..`, but graphically.
|
||||
|
||||
## Git a summary, with `git log --oneline`
|
||||
|
||||
Try `git log --graph --oneline --decorate --boundary`. (Quite a mouthful;
|
||||
Greg has this aliased as `git k`, in homage to `gitk`.) It can be a
|
||||
lightweight alternative to your graphical client for simple, routine
|
||||
situations, giving a compact list of commits each on just one line.
|
||||
|
||||
- To list the commits local to your current branch: `git k @{u}..`.
|
||||
(Greg has an alias for this, and types it constantly.)
|
||||
|
||||
- To list all your own local commits on all branches:
|
||||
`git k --branches @ --not --remotes=origin --remotes=upstream`.
|
||||
(For explanation, see `git help log`.)
|
||||
64
docs/git/reviewing.md
Normal file
64
docs/git/reviewing.md
Normal file
@@ -0,0 +1,64 @@
|
||||
# Review changes
|
||||
|
||||
**Note** - The following section covers reviewing changes on your local
|
||||
clone. Please read the section on [code reviews][zulip-rtd-review] for a guide
|
||||
on reviewing changes by other contributors.
|
||||
|
||||
## Changes on (local) working tree
|
||||
|
||||
Display changes between index and working tree (what is not yet staged for commit):
|
||||
|
||||
```console
|
||||
$ git diff
|
||||
```
|
||||
|
||||
Display changes between index and last commit (what you have staged for commit):
|
||||
|
||||
```console
|
||||
$ git diff --cached
|
||||
```
|
||||
|
||||
Display changes in working tree since last commit (changes that are staged as
|
||||
well as ones that are not):
|
||||
|
||||
```console
|
||||
$ git diff HEAD
|
||||
```
|
||||
|
||||
## Changes within branches
|
||||
|
||||
Use any git-ref to compare changes between two commits on the current branch.
|
||||
|
||||
Display changes between commit before last and last commit:
|
||||
|
||||
```console
|
||||
$ git diff HEAD^ HEAD
|
||||
```
|
||||
|
||||
Display changes between two commits using their hashes:
|
||||
|
||||
```console
|
||||
$ git diff e2f404c 7977169
|
||||
```
|
||||
|
||||
## Changes between branches
|
||||
|
||||
Display changes between tip of `topic` branch and tip of `main` branch:
|
||||
|
||||
```console
|
||||
$ git diff topic main
|
||||
```
|
||||
|
||||
Display changes that have occurred on `main` branch since `topic` branch was created:
|
||||
|
||||
```console
|
||||
$ git diff topic...main
|
||||
```
|
||||
|
||||
Display changes you've committed so far since creating a branch from `upstream/main`:
|
||||
|
||||
```console
|
||||
$ git diff upstream/main...HEAD
|
||||
```
|
||||
|
||||
[zulip-rtd-review]: ../contributing/code-reviewing.md
|
||||
72
docs/git/setup.md
Normal file
72
docs/git/setup.md
Normal file
@@ -0,0 +1,72 @@
|
||||
# Set up Git
|
||||
|
||||
If you're already using Git, have a client you like, and a GitHub account, you
|
||||
can skip this section. Otherwise, read on!
|
||||
|
||||
## Install and configure Git, join GitHub
|
||||
|
||||
If you're not already using Git, you might need to [install][gitbook-install]
|
||||
and [configure][gitbook-setup] it.
|
||||
|
||||
**If you are using Windows 10 without [WSL
|
||||
2](https://docs.microsoft.com/en-us/windows/wsl/wsl2-about), make sure you
|
||||
[are running Git BASH as an administrator][git-bash-admin] at all times.**
|
||||
|
||||
You'll also need a GitHub account, which you can sign up for
|
||||
[here][github-join].
|
||||
|
||||
We highly recommend you create an SSH key if you don't already have
|
||||
one and [add it to your GitHub account][github-help-add-ssh-key]. If
|
||||
you don't, you'll have to type your GitHub username and password every
|
||||
time you interact with GitHub, which is usually several times a day.
|
||||
|
||||
We also highly recommend the following:
|
||||
|
||||
- [Configure Git][gitbook-config] with your name and email and
|
||||
[aliases][gitbook-aliases] for commands you'll use often. We
|
||||
recommend using your full name (not just your first name), since
|
||||
that's what we'll use to give credit to your work in places like the
|
||||
Zulip release notes.
|
||||
- Install the command auto-completion and/or git-prompt plugins available for
|
||||
[Bash][gitbook-other-envs-bash] and [Zsh][gitbook-other-envs-zsh].
|
||||
|
||||
If you are installing the Zulip development environment, now you are ready to
|
||||
continue with [Step 1: Install prerequisites](../development/setup-recommended.md#step-1-install-prerequisites).
|
||||
|
||||
## Get a graphical client
|
||||
|
||||
Even if you're comfortable using Git on the command line, having a graphical
|
||||
client can be useful for viewing your repository. This is especially true
|
||||
when doing complicated rebases and similar operations because you can check
|
||||
the state of your repository after each command to see what changed. If
|
||||
something goes wrong, this helps you figure out when and why.
|
||||
|
||||
If you don't already have one installed, here are some suggestions:
|
||||
|
||||
- macOS: [GitX][gitgui-gitx] (previously [GitX-dev][gitgui-gitxdev])
|
||||
- Ubuntu/Linux: [git-cola][gitgui-gitcola], [gitg][gitgui-gitg], [gitk][gitgui-gitk]
|
||||
- Windows: [SourceTree][gitgui-sourcetree]
|
||||
|
||||
If you like working on the command line, but want better visualization and
|
||||
navigation of your Git repo, try [Tig][tig], a cross-platform ncurses-based
|
||||
text-mode interface to Git.
|
||||
|
||||
And, if none of the above are to your liking, try [one of these][gitbook-guis].
|
||||
|
||||
[git-bash-admin]: ../development/setup-advanced.md#running-git-bash-as-an-administrator
|
||||
[gitbook-aliases]: https://git-scm.com/book/en/v2/Git-Basics-Git-Aliases
|
||||
[gitbook-config]: https://git-scm.com/book/en/v2/Customizing-Git-Git-Configuration
|
||||
[gitbook-guis]: https://git-scm.com/downloads/guis
|
||||
[gitbook-install]: https://git-scm.com/book/en/v2/Getting-Started-Installing-Git
|
||||
[github-join]: https://github.com/join
|
||||
[gitbook-setup]: https://git-scm.com/book/en/v2/Getting-Started-First-Time-Git-Setup
|
||||
[gitbook-other-envs-bash]: https://git-scm.com/book/en/v2/Appendix-A%3A-Git-in-Other-Environments-Git-in-Bash
|
||||
[gitbook-other-envs-zsh]: https://git-scm.com/book/en/v2/Appendix-A%3A-Git-in-Other-Environments-Git-in-Zsh
|
||||
[gitgui-gitcola]: https://git-cola.github.io/
|
||||
[gitgui-gitg]: https://wiki.gnome.org/Apps/Gitg
|
||||
[gitgui-gitk]: https://git-scm.com/docs/gitk
|
||||
[gitgui-gitx]: https://github.com/gitx/gitx/
|
||||
[gitgui-gitxdev]: https://rowanj.github.io/gitx/
|
||||
[gitgui-sourcetree]: https://www.sourcetreeapp.com/
|
||||
[github-help-add-ssh-key]: https://help.github.com/en/articles/adding-a-new-ssh-key-to-your-github-account
|
||||
[tig]: https://jonas.github.io/tig/
|
||||
96
docs/git/terminology.md
Normal file
96
docs/git/terminology.md
Normal file
@@ -0,0 +1,96 @@
|
||||
# Important Git terms
|
||||
|
||||
When you install Git, it adds a manual entry for `gitglossary`. You can view
|
||||
this glossary by running `man gitglossary`. Below we've included the Git terms
|
||||
you'll encounter most often along with their definitions from _gitglossary_.
|
||||
|
||||
## branch
|
||||
|
||||
A "branch" is an active line of development. The most recent commit
|
||||
on a branch is referred to as the tip of that branch. The tip of
|
||||
the branch is referenced by a branch head, which moves forward as
|
||||
additional development is done on the branch. A single Git
|
||||
repository can track an arbitrary number of branches, but your
|
||||
working tree is associated with just one of them (the "current" or
|
||||
"checked out" branch), and HEAD points to that branch.
|
||||
|
||||
## cache
|
||||
|
||||
Obsolete for: index
|
||||
|
||||
## checkout
|
||||
|
||||
The action of updating all or part of the working tree with a tree
|
||||
object or blob from the object database, and updating the index and
|
||||
HEAD if the whole working tree has been pointed at a new branch.
|
||||
|
||||
## commit
|
||||
|
||||
As a noun: A single point in the Git history; the entire history of
|
||||
a project is represented as a set of interrelated commits. The word
|
||||
"commit" is often used by Git in the same places other revision
|
||||
control systems use the words "revision" or "version". Also used as
|
||||
a short hand for commit object.
|
||||
|
||||
As a verb: The action of storing a new snapshot of the project's
|
||||
state in the Git history, by creating a new commit representing the
|
||||
current state of the index and advancing HEAD to point at the new
|
||||
|
||||
## fast-forward
|
||||
|
||||
A fast-forward is a special type of merge where you have a revision
|
||||
and you are "merging" another branch's changes that happen to be a
|
||||
descendant of what you have. In such these cases, you do not make a
|
||||
new merge commit but instead just update to their revision. This will
|
||||
happen frequently on a remote-tracking branch of a remote
|
||||
repository.
|
||||
|
||||
## fetch
|
||||
|
||||
Fetching a branch means to get the branch's head ref from a remote
|
||||
repository, to find out which objects are missing from the local
|
||||
object database, and to get them, too. See also [git-fetch(1)](https://git-scm.com/docs/git-fetch)
|
||||
|
||||
## hash
|
||||
|
||||
In Git's context, synonym for object name.
|
||||
|
||||
## head
|
||||
|
||||
A named reference to the commit at the tip of a branch. Heads are
|
||||
stored in a file in $GIT_DIR/refs/heads/ directory, except when
|
||||
using packed refs. See also [git-pack-refs(1)](https://git-scm.com/docs/git-pack-refs).
|
||||
|
||||
## HEAD
|
||||
|
||||
The current branch. In more detail: Your working tree is normally
|
||||
derived from the state of the tree referred to by HEAD. HEAD is a
|
||||
reference to one of the heads in your repository, except when using
|
||||
a detached HEAD, in which case it directly references an arbitrary
|
||||
commit.
|
||||
|
||||
## index
|
||||
|
||||
A collection of files with stat information, whose contents are
|
||||
stored as objects. The index is a stored version of your working
|
||||
tree. Truth be told, it can also contain a second, and even a third
|
||||
version of a working tree, which are used when merging.
|
||||
|
||||
## pull
|
||||
|
||||
Pulling a branch means to fetch it and merge it. See also [git-pull(1)](https://git-scm.com/docs/git-pull)
|
||||
|
||||
## push
|
||||
|
||||
Pushing a branch means to get the branch's head ref from a remote
|
||||
repository, find out if it is a direct ancestor to the branch's
|
||||
local head ref, and in that case, putting all objects, which are
|
||||
reachable from the local head ref, and which are missing from the
|
||||
remote repository, into the remote object database, and updating
|
||||
the remote head ref. If the remote head is not an ancestor to the
|
||||
local head, the push fails.
|
||||
|
||||
## rebase
|
||||
|
||||
To reapply a series of changes from a branch to a different base,
|
||||
and reset the head of that branch to the result.
|
||||
64
docs/git/the-git-difference.md
Normal file
64
docs/git/the-git-difference.md
Normal file
@@ -0,0 +1,64 @@
|
||||
# How Git is different
|
||||
|
||||
Whether you're new to Git or have experience with another version control
|
||||
system (VCS), it's a good idea to learn a bit about how Git works. We recommend
|
||||
this excellent presentation _[Understanding Git][understanding-git]_ from
|
||||
Nelson Elhage and Anders Kaseorg and the [Git Basics][gitbook-basics] chapter
|
||||
from _Pro Git_ by Scott Chacon and Ben Straub.
|
||||
|
||||
Here are the top things to know:
|
||||
|
||||
- **Git works on snapshots.** Unlike other version control systems (e.g.,
|
||||
Subversion, Perforce, Bazaar), which track files and changes to those files
|
||||
made over time, Git tracks _snapshots_ of your project. Each time you commit
|
||||
or otherwise make a change to your repository, Git takes a snapshot of your
|
||||
project and stores a reference to that snapshot. If a file hasn't changed,
|
||||
Git creates a link to the identical file rather than storing it again.
|
||||
|
||||
- **Most Git operations are local.** Git is a distributed version control
|
||||
system, so once you've cloned a repository, you have a complete copy of that
|
||||
repository's _entire history_. Staging, committing, branching, and browsing
|
||||
history are all things you can do locally without network access and without
|
||||
immediately affecting any remote repositories. To make or receive changes
|
||||
from remote repositories, you need to `git fetch`, `git pull`, or `git push`.
|
||||
|
||||
- **Nearly all Git actions add information to the Git database**, rather than
|
||||
removing it. As such, it's hard to make Git perform actions that you can't
|
||||
undo. However, Git can't undo what it doesn't know about, so it's a good
|
||||
practice to frequently commit your changes and frequently push your commits to
|
||||
your remote repository.
|
||||
|
||||
- **Git is designed for lightweight branching and merging.** Branches are
|
||||
simply references to snapshots. It's okay and expected to make a lot of
|
||||
branches, even throwaway and experimental ones.
|
||||
|
||||
- **Git stores all data as objects, of which there are four types:** blob
|
||||
(file), tree (directory), commit (revision), and tag. Each of these objects
|
||||
is named by a unique hash, the SHA-1 hash of its contents. Most of the time
|
||||
you'll refer to objects by their truncated hash or more human-readable
|
||||
reference like `HEAD` (the current branch). Blobs and trees represent files
|
||||
and directories. Tags are named references to other objects. A commit object
|
||||
includes: tree id, zero or more parents as commit ids, an author (name,
|
||||
email, date), a committer (name, email, date), and a log message. A Git
|
||||
repository is a collection of mutable pointers to these objects called
|
||||
**refs**.
|
||||
|
||||
- **Cloning a repository creates a working copy.** Every working copy has a
|
||||
`.git` subdirectory, which contains its own Git repository. The `.git`
|
||||
subdirectory also tracks the _index_, a staging area for changes that will
|
||||
become part of the next commit. All files outside of `.git` are the _working
|
||||
tree_.
|
||||
|
||||
- **Files tracked with Git have three possible states: committed, modified, and
|
||||
staged.** Committed files are those safely stored in your local `.git`
|
||||
repository/database. Staged files have changes and have been marked for
|
||||
inclusion in the next commit; they are part of the index. Modified files have
|
||||
changes but have not yet been marked for inclusion in the next commit; they
|
||||
have not been added to the index.
|
||||
|
||||
- **Git commit workflow is as follows.** Edit files in your _working tree_. Add
|
||||
to the _index_ (that is _stage_) with `git add`. _Commit_ to the HEAD of the
|
||||
current branch with `git commit`.
|
||||
|
||||
[gitbook-basics]: https://git-scm.com/book/en/v2/Git-Basics-Getting-a-Git-Repository
|
||||
[understanding-git]: https://web.mit.edu/nelhage/Public/git-slides-2009.pdf
|
||||
284
docs/git/troubleshooting.md
Normal file
284
docs/git/troubleshooting.md
Normal file
@@ -0,0 +1,284 @@
|
||||
# Get and stay out of trouble
|
||||
|
||||
Git is a powerful yet complex version control system. Even for contributors
|
||||
experienced at using version control, it can be confusing. The good news is
|
||||
that nearly all Git actions add information to the Git database, rather than
|
||||
removing it. As such, it's hard to make Git perform actions that you can't
|
||||
undo. However, Git can't undo what it doesn't know about, so it's a good
|
||||
practice to frequently commit your changes and frequently push your commits to
|
||||
your remote repository.
|
||||
|
||||
## Undo a merge commit
|
||||
|
||||
A merge commit is a special type of commit that has two parent commits. It's
|
||||
created by Git when you merge one branch into another and the last commit on
|
||||
your current branch is not a direct ancestor of the branch you are trying to
|
||||
merge in. This happens quite often in a busy project like Zulip where there are
|
||||
many contributors because upstream/zulip will have new commits while you're
|
||||
working on a feature or bugfix. In order for Git to merge your changes and the
|
||||
changes that have occurred on zulip/upstream since you first started your work,
|
||||
it must perform a three-way merge and create a merge commit.
|
||||
|
||||
Merge commits aren't bad, however, Zulip doesn't use them. Instead Zulip uses a
|
||||
forked-repo, rebase-oriented workflow.
|
||||
|
||||
A merge commit is usually created when you've run `git pull` or `git merge`.
|
||||
You'll know you're creating a merge commit if you're prompted for a commit
|
||||
message and the default is something like this:
|
||||
|
||||
```text
|
||||
Merge branch 'main' of https://github.com/zulip/zulip
|
||||
|
||||
# Please enter a commit message to explain why this merge is necessary,
|
||||
# especially if it merges an updated upstream into a topic branch.
|
||||
#
|
||||
# Lines starting with '#' will be ignored, and an empty message aborts
|
||||
# the commit.
|
||||
```
|
||||
|
||||
And the first entry for `git log` will show something like:
|
||||
|
||||
```console
|
||||
commit e5f8211a565a5a5448b93e98ed56415255546f94
|
||||
Merge: 13bea0e e0c10ed
|
||||
Author: Christie Koehler <ck@christi3k.net>
|
||||
Date: Mon Oct 10 13:25:51 2016 -0700
|
||||
|
||||
Merge branch 'main' of https://github.com/zulip/zulip
|
||||
```
|
||||
|
||||
Some graphical Git clients may also create merge commits.
|
||||
|
||||
To undo a merge commit, first run `git reflog` to identify the commit you want
|
||||
to roll back to:
|
||||
|
||||
```console
|
||||
$ git reflog
|
||||
|
||||
e5f8211 HEAD@{0}: pull upstream main: Merge made by the 'recursive' strategy.
|
||||
13bea0e HEAD@{1}: commit: test commit for docs.
|
||||
```
|
||||
|
||||
Reflog output will be long. The most recent Git refs will be listed at the top.
|
||||
In the example above `e5f8211 HEAD@{0}:` is the merge commit made automatically
|
||||
by `git pull` and `13bea0e HEAD@{1}:` is the last commit I made before running
|
||||
`git pull`, the commit that I want to rollback to.
|
||||
|
||||
Once you'd identified the ref you want to revert to, you can do so with [git
|
||||
reset][gitbook-reset]:
|
||||
|
||||
```console
|
||||
$ git reset --hard 13bea0e
|
||||
HEAD is now at 13bea0e test commit for docs.
|
||||
```
|
||||
|
||||
:::{important}
|
||||
`git reset --hard <commit>` will discard all changes in your
|
||||
working directory and index since the commit you're resetting to with
|
||||
`<commit>`. _This is the main way you can lose work in Git_. If you need
|
||||
to keep any changes that are in your working directory or that you have
|
||||
committed, use `git reset --merge <commit>` instead.
|
||||
:::
|
||||
|
||||
You can also use the relative reflog `HEAD@{1}` instead of the commit hash,
|
||||
just keep in mind that this changes as you run Git commands.
|
||||
|
||||
Now when you look at the output of `git reflog`, you should see that the tip of your branch points to your
|
||||
last commit `13bea0e` before the merge:
|
||||
|
||||
```console
|
||||
$ git reflog
|
||||
|
||||
13bea0e HEAD@{2}: reset: moving to HEAD@{1}
|
||||
e5f8211 HEAD@{3}: pull upstream main: Merge made by the 'recursive' strategy.
|
||||
13bea0e HEAD@{4}: commit: test commit for docs.
|
||||
```
|
||||
|
||||
And the first entry `git log` shows is this:
|
||||
|
||||
```console
|
||||
commit 13bea0e40197b1670e927a9eb05aaf50df9e8277
|
||||
Author: Christie Koehler <ck@christi3k.net>
|
||||
Date: Mon Oct 10 13:25:38 2016 -0700
|
||||
|
||||
test commit for docs.
|
||||
```
|
||||
|
||||
## Restore a lost commit
|
||||
|
||||
We've mentioned you can use `git reset --hard` to rollback to a previous
|
||||
commit. What if you run `git reset --hard` and then realize you actually need
|
||||
one or more of the commits you just discarded? No problem, you can restore them
|
||||
with `git cherry-pick` ([docs][gitbook-git-cherry-pick]).
|
||||
|
||||
For example, let's say you just committed "some work" and your `git log` looks
|
||||
like this:
|
||||
|
||||
```console
|
||||
* 67aea58 (HEAD -> main) some work
|
||||
* 13bea0e test commit for docs.
|
||||
```
|
||||
|
||||
You then mistakenly run `git reset --hard 13bea0e`:
|
||||
|
||||
```console
|
||||
$ git reset --hard 13bea0e
|
||||
HEAD is now at 13bea0e test commit for docs.
|
||||
|
||||
$ git log
|
||||
* 13bea0e (HEAD -> main) test commit for docs.
|
||||
```
|
||||
|
||||
And then realize you actually needed to keep commit 67aea58. First, use
|
||||
`git reflog` to confirm that commit you want to restore and then run
|
||||
`git cherry-pick <commit>`:
|
||||
|
||||
```console
|
||||
$ git reflog
|
||||
13bea0e HEAD@{0}: reset: moving to 13bea0e
|
||||
67aea58 HEAD@{1}: commit: some work
|
||||
|
||||
$ git cherry-pick 67aea58
|
||||
[main 67aea58] some work
|
||||
Date: Thu Oct 13 11:51:19 2016 -0700
|
||||
1 file changed, 1 insertion(+)
|
||||
create mode 100644 test4.txt
|
||||
```
|
||||
|
||||
## Recover from a `git rebase` failure
|
||||
|
||||
One situation in which `git rebase` will fail and require you to intervene is
|
||||
when your change, which Git will try to re-apply on top of new commits from
|
||||
which ever branch you are rebasing on top of, is to code that has been changed
|
||||
by those new commits.
|
||||
|
||||
For example, while I'm working on a file, another contributor makes a change to
|
||||
that file, submits a pull request and has their code merged into `main`.
|
||||
Usually this is not a problem, but in this case the other contributor made a
|
||||
change to a part of the file I also want to change. When I try to bring my
|
||||
branch up to date with `git fetch` and then `git rebase upstream/main`, I see
|
||||
the following:
|
||||
|
||||
```console
|
||||
First, rewinding head to replay your work on top of it...
|
||||
Applying: test change for docs
|
||||
Using index info to reconstruct a base tree...
|
||||
M README.md
|
||||
Falling back to patching base and 3-way merge...
|
||||
Auto-merging README.md
|
||||
CONFLICT (content): Merge conflict in README.md
|
||||
error: Failed to merge in the changes.
|
||||
Patch failed at 0001 test change for docs
|
||||
The copy of the patch that failed is found in: .git/rebase-apply/patch
|
||||
|
||||
When you have resolved this problem, run "git rebase --continue".
|
||||
If you prefer to skip this patch, run "git rebase --skip" instead.
|
||||
To check out the original branch and stop rebasing, run "git rebase --abort".
|
||||
```
|
||||
|
||||
This message tells me that Git was not able to apply my changes to README.md
|
||||
after bringing in the new commits from upstream/main.
|
||||
|
||||
Running `git status` also gives me some information:
|
||||
|
||||
```console
|
||||
rebase in progress; onto 5ae56e6
|
||||
You are currently rebasing branch 'docs-test' on '5ae56e6'.
|
||||
(fix conflicts and then run "git rebase --continue")
|
||||
(use "git rebase --skip" to skip this patch)
|
||||
(use "git rebase --abort" to check out the original branch)
|
||||
|
||||
Unmerged paths:
|
||||
(use "git reset HEAD <file>..." to unstage)
|
||||
(use "git add <file>..." to mark resolution)
|
||||
|
||||
both modified: README.md
|
||||
|
||||
no changes added to commit (use "git add" and/or "git commit -a")
|
||||
```
|
||||
|
||||
To fix, open all the files with conflicts in your editor and decide which edits
|
||||
should be applied. Git uses standard conflict-resolution (`<<<<<<<`, `=======`,
|
||||
and `>>>>>>>`) markers to indicate where in files there are conflicts.
|
||||
|
||||
Tip: You can see recent changes made to a file by running the following
|
||||
commands:
|
||||
|
||||
```bash
|
||||
git fetch upstream
|
||||
git log -p upstream/main -- /path/to/file
|
||||
```
|
||||
|
||||
You can use this to compare the changes that you have made to a file with the
|
||||
ones in upstream, helping you avoid undoing changes from a previous commit when
|
||||
you are rebasing.
|
||||
|
||||
Once you've done that, save the file(s), stage them with `git add` and then
|
||||
continue the rebase with `git rebase --continue`:
|
||||
|
||||
```console
|
||||
$ git add README.md
|
||||
|
||||
$ git rebase --continue
|
||||
Applying: test change for docs
|
||||
```
|
||||
|
||||
For help resolving merge conflicts, see [basic merge
|
||||
conflicts][gitbook-basic-merge-conflicts], [advanced
|
||||
merging][gitbook-advanced-merging], and/or GitHub's help on [how to resolve a
|
||||
merge conflict][github-help-resolve-merge-conflict].
|
||||
|
||||
## Working from multiple computers
|
||||
|
||||
Working from multiple computers with Zulip and Git is fine, but you'll need to
|
||||
pay attention and do a bit of work to ensure all of your work is readily
|
||||
available.
|
||||
|
||||
Recall that most Git operations are local. When you commit your changes with
|
||||
`git commit` they are safely stored in your _local_ Git database only. That is,
|
||||
until you _push_ the commits to GitHub, they are only available on the computer
|
||||
where you committed them.
|
||||
|
||||
So, before you stop working for the day, or before you switch computers, push
|
||||
all of your commits to GitHub with `git push`:
|
||||
|
||||
```console
|
||||
$ git push origin <branchname>
|
||||
```
|
||||
|
||||
When you first start working on a new computer, you'll [clone the Zulip
|
||||
repository][clone-to-your-machine] and [connect it to Zulip
|
||||
upstream][connect-upstream]. A clone retrieves all current commits,
|
||||
including the ones you pushed to GitHub from your other computer.
|
||||
|
||||
But if you're switching to another computer on which you have already cloned
|
||||
Zulip, you need to update your local Git database with new refs from your
|
||||
GitHub fork. You do this with `git fetch`:
|
||||
|
||||
```console
|
||||
$ git fetch <username>
|
||||
```
|
||||
|
||||
Ideally you should do this before you have made any commits on the same branch
|
||||
on the second computer. Then you can `git merge` on whichever branch you need
|
||||
to update:
|
||||
|
||||
```console
|
||||
$ git checkout <my-branch>
|
||||
Switched to branch '<my-branch>'
|
||||
|
||||
$ git merge origin/main
|
||||
```
|
||||
|
||||
**If you have already made commits on the second computer that you need to
|
||||
keep,** you'll need to use `git log FETCH_HEAD` to identify that hashes of the
|
||||
commits you want to keep and then `git cherry-pick <commit>` those commits into
|
||||
whichever branch you need to update.
|
||||
|
||||
[clone-to-your-machine]: cloning.md#step-1b-clone-to-your-machine
|
||||
[connect-upstream]: cloning.md#step-1c-connect-your-fork-to-zulip-upstream
|
||||
[gitbook-advanced-merging]: https://git-scm.com/book/en/v2/Git-Tools-Advanced-Merging#_advanced_merging
|
||||
[gitbook-basic-merge-conflicts]: https://git-scm.com/book/en/v2/Git-Branching-Basic-Branching-and-Merging#Basic-Merge-Conflicts
|
||||
[gitbook-git-cherry-pick]: https://git-scm.com/docs/git-cherry-pick
|
||||
[gitbook-reset]: https://git-scm.com/docs/git-reset
|
||||
[github-help-resolve-merge-conflict]: https://help.github.com/en/articles/resolving-a-merge-conflict-using-the-command-line
|
||||
457
docs/git/using.md
Normal file
457
docs/git/using.md
Normal file
@@ -0,0 +1,457 @@
|
||||
# Using Git as you work
|
||||
|
||||
## Know what branch you're working on
|
||||
|
||||
When using Git, it's important to know which branch you currently have checked
|
||||
out because most Git commands implicitly operate on the current branch. You can
|
||||
determine the currently checked out branch several ways.
|
||||
|
||||
One way is with [git status][gitbook-git-status]:
|
||||
|
||||
```console
|
||||
$ git status
|
||||
On branch issue-demo
|
||||
nothing to commit, working directory clean
|
||||
```
|
||||
|
||||
Another is with [git branch][gitbook-git-branch] which will display all local
|
||||
branches, with a star next to the current branch:
|
||||
|
||||
```console
|
||||
$ git branch
|
||||
* issue-demo
|
||||
main
|
||||
```
|
||||
|
||||
To see even more information about your branches, including remote branches,
|
||||
use `git branch -vva`:
|
||||
|
||||
```console
|
||||
$ git branch -vva
|
||||
* issue-123 517468b troubleshooting tip about provisioning
|
||||
main f0eaee6 [origin/main] bug: Fix traceback in get_missed_message_token_from_address().
|
||||
remotes/origin/HEAD -> origin/main
|
||||
remotes/origin/issue-1234 4aeccb7 Another test commit, with longer message.
|
||||
remotes/origin/main f0eaee6 bug: Fix traceback in get_missed_message_token_from_address().
|
||||
remotes/upstream/main dbeab6a Optimize checks of test database state by moving into Python.
|
||||
```
|
||||
|
||||
You can also configure [Bash][gitbook-other-envs-bash] and
|
||||
[Zsh][gitbook-other-envs-zsh] to display the current branch in your prompt.
|
||||
|
||||
## Keep your fork up to date
|
||||
|
||||
You'll want to [keep your fork][github-help-sync-fork] up-to-date with changes
|
||||
from Zulip's main repositories.
|
||||
|
||||
**Note about `git pull`**: You might be used to using `git pull` on other
|
||||
projects. With Zulip, because we don't use merge commits, you'll want to avoid
|
||||
it. Rather than using `git pull`, which by default is a shortcut for
|
||||
`git fetch && git merge FETCH_HEAD` ([docs][gitbook-git-pull]), you
|
||||
should use `git fetch` and then `git rebase`.
|
||||
|
||||
First, [fetch][gitbook-fetch] changes from Zulip's upstream repository you
|
||||
configured in the step above:
|
||||
|
||||
```console
|
||||
$ git fetch upstream
|
||||
```
|
||||
|
||||
Next, check out your `main` branch and [rebase][gitbook-git-rebase] it on top
|
||||
of `upstream/main`:
|
||||
|
||||
```console
|
||||
$ git checkout main
|
||||
Switched to branch 'main'
|
||||
|
||||
$ git rebase upstream/main
|
||||
```
|
||||
|
||||
This will rollback any changes you've made to `main`, update it from
|
||||
`upstream/main`, and then re-apply your changes. Rebasing keeps the commit
|
||||
history clean and readable.
|
||||
|
||||
When you're ready, [push your changes][github-help-push] to your remote fork.
|
||||
Make sure you're in branch `main` and then run `git push`:
|
||||
|
||||
```console
|
||||
$ git checkout main
|
||||
$ git push origin main
|
||||
```
|
||||
|
||||
You can keep any branch up to date using this method. If you're working on a
|
||||
feature branch (see next section), which we recommend, you would change the
|
||||
command slightly, using the name of your `feature-branch` rather than `main`:
|
||||
|
||||
```console
|
||||
$ git checkout feature-branch
|
||||
Switched to branch 'feature-branch'
|
||||
|
||||
$ git rebase upstream/main
|
||||
|
||||
$ git push origin feature-branch
|
||||
```
|
||||
|
||||
## Work on a feature branch
|
||||
|
||||
One way to keep your work organized is to create a branch for each issue or
|
||||
feature. Recall from [how Git is different][how-git-is-different] that
|
||||
**Git is designed for lightweight branching and merging.** You can and should
|
||||
create as many branches as you'd like.
|
||||
|
||||
First, make sure your `main` branch is up-to-date with Zulip upstream ([see
|
||||
how][zulip-git-guide-up-to-date]).
|
||||
|
||||
Next, from your `main` branch, create a new tracking branch, providing a
|
||||
descriptive name for your feature branch:
|
||||
|
||||
```console
|
||||
$ git checkout main
|
||||
Switched to branch 'main'
|
||||
|
||||
$ git checkout -b issue-1755-fail2ban
|
||||
Switched to a new branch 'issue-1755-fail2ban'
|
||||
```
|
||||
|
||||
Alternatively, you can create a new branch explicitly based off
|
||||
`upstream/main`:
|
||||
|
||||
```console
|
||||
$ git checkout -b issue-1755-fail2ban upstream/main
|
||||
Switched to a new branch 'issue-1755-fail2ban'
|
||||
```
|
||||
|
||||
Now you're ready to work on the issue or feature.
|
||||
|
||||
## Run linters and tests locally
|
||||
|
||||
In addition to having GitHub Actions run tests and linters each time you
|
||||
push a new commit, you can also run them locally. See
|
||||
[testing](../testing/testing.md) for details.
|
||||
|
||||
## Stage changes
|
||||
|
||||
Recall that files tracked with Git have three possible states:
|
||||
committed, modified, and staged.
|
||||
|
||||
To prepare a commit, first add the files with changes that you want
|
||||
to include in your commit to your staging area. You _add_ both new files and
|
||||
existing ones. You can also remove files from staging when necessary.
|
||||
|
||||
### Get status of working directory
|
||||
|
||||
To see what files in the working directory have changes that have not been
|
||||
staged, use `git status`.
|
||||
|
||||
If you have no changes in the working directory, you'll see something like
|
||||
this:
|
||||
|
||||
```console
|
||||
$ git status
|
||||
On branch issue-123
|
||||
nothing to commit, working directory clean
|
||||
```
|
||||
|
||||
If you have unstaged changes, you'll see something like this:
|
||||
|
||||
```console
|
||||
On branch issue-123
|
||||
Untracked files:
|
||||
(use "git add <file>..." to include in what will be committed)
|
||||
|
||||
newfile.py
|
||||
|
||||
nothing added to commit but untracked files present (use "git add" to track)
|
||||
```
|
||||
|
||||
### Stage additions with `git add`
|
||||
|
||||
To add changes to your staging area, use `git add <filename>`. Because
|
||||
`git add` is all about staging the changes you want to commit, you use
|
||||
it to add _new files_ as well as _files with changes_ to your staging
|
||||
area.
|
||||
|
||||
Continuing our example from above, after we run `git add newfile.py`, we'll see
|
||||
the following from `git status`:
|
||||
|
||||
```console
|
||||
On branch issue-123
|
||||
Changes to be committed:
|
||||
(use "git reset HEAD <file>..." to unstage)
|
||||
|
||||
new file: newfile.py
|
||||
```
|
||||
|
||||
You can view the changes in files you have staged with `git diff --cached`. To
|
||||
view changes to files you haven't yet staged, just use `git diff`.
|
||||
|
||||
If you want to add all changes in the working directory, use `git add -A`
|
||||
([documentation][gitbook-add]).
|
||||
|
||||
You can also stage changes using your graphical Git client.
|
||||
|
||||
If you stage a file, you can undo it with `git reset HEAD <filename>`. Here's
|
||||
an example where we stage a file `test3.txt` and then unstage it:
|
||||
|
||||
```console
|
||||
$ git add test3.txt
|
||||
On branch issue-1234
|
||||
Changes to be committed:
|
||||
(use "git reset HEAD <file>..." to unstage)
|
||||
|
||||
new file: test3.txt
|
||||
|
||||
$ git reset HEAD test3.txt
|
||||
$ git status
|
||||
On branch issue-1234
|
||||
Untracked files:
|
||||
(use "git add <file>..." to include in what will be committed)
|
||||
|
||||
test3.txt
|
||||
|
||||
nothing added to commit but untracked files present (use "git add" to track)
|
||||
```
|
||||
|
||||
### Stage deletions with `git rm`
|
||||
|
||||
To remove existing files from your repository, use `git rm`
|
||||
([documentation][gitbook-rm]). This command can either stage the file for
|
||||
removal from your repository AND delete it from your working directory or just
|
||||
stage the file for deletion and leave it in your working directory.
|
||||
|
||||
To stage a file for deletion and **remove** it from your working directory, use
|
||||
`git rm <filename>`:
|
||||
|
||||
```console
|
||||
$ git rm test.txt
|
||||
rm 'test.txt'
|
||||
|
||||
$ git status
|
||||
On branch issue-1234
|
||||
Changes to be committed:
|
||||
(use "git reset HEAD <file>..." to unstage)
|
||||
|
||||
deleted: test.txt
|
||||
|
||||
$ ls test.txt
|
||||
ls: No such file or directory
|
||||
```
|
||||
|
||||
To stage a file for deletion and **keep** it in your working directory, use
|
||||
`git rm --cached <filename>`:
|
||||
|
||||
```console
|
||||
$ git rm --cached test2.txt
|
||||
rm 'test2.txt'
|
||||
|
||||
$ git status
|
||||
On branch issue-1234
|
||||
Changes to be committed:
|
||||
(use "git reset HEAD <file>..." to unstage)
|
||||
|
||||
deleted: test2.txt
|
||||
|
||||
$ ls test2.txt
|
||||
test2.txt
|
||||
```
|
||||
|
||||
If you stage a file for deletion with the `--cached` option, and haven't yet
|
||||
run `git commit`, you can undo it with `git reset HEAD <filename>`:
|
||||
|
||||
```console
|
||||
$ git reset HEAD test2.txt
|
||||
```
|
||||
|
||||
Unfortunately, you can't restore a file deleted with `git rm` if you didn't use
|
||||
the `--cache` option. However, `git rm` only deletes files it knows about.
|
||||
Files you have never added to Git won't be deleted.
|
||||
|
||||
## Commit changes
|
||||
|
||||
When you've staged all your changes, you're ready to commit. You can do this
|
||||
with `git commit -m "My commit message."` to include a commit message.
|
||||
|
||||
Here's an example of committing with the `-m` for a one-line commit message:
|
||||
|
||||
```console
|
||||
$ git commit -m "Add a test commit for docs."
|
||||
[issue-123 173e17a] Add a test commit for docs.
|
||||
1 file changed, 1 insertion(+)
|
||||
create mode 100644 newfile.py
|
||||
```
|
||||
|
||||
You can also use `git commit` without the `-m` option and your editor to open,
|
||||
allowing you to easily draft a multi-line commit message.
|
||||
|
||||
How long your commit message should be depends on where you are in your work.
|
||||
Using short, one-line messages for commits related to in-progress work makes
|
||||
sense. For a commit that you intend to be final or that encompasses a
|
||||
significant amount or complex work, you should include a longer message.
|
||||
|
||||
Keep in mind that your commit should contain a 'minimal coherent idea' and have
|
||||
a quality commit message. See Zulip docs [Commit
|
||||
Discipline][zulip-rtd-commit-discipline] and [Commit
|
||||
messages][zulip-rtd-commit-messages] for details.
|
||||
|
||||
Here's an example of a longer commit message that will be used for a pull request:
|
||||
|
||||
```text
|
||||
Integrate Fail2Ban.
|
||||
|
||||
Updates Zulip logging to put an unambiguous entry into the logs such
|
||||
that fail2ban can be configured to look for these entries.
|
||||
|
||||
Tested on my local Ubuntu development server, but would appreciate
|
||||
someone testing on a production install with more users.
|
||||
|
||||
Fixes #1755.
|
||||
```
|
||||
|
||||
The first line is the summary. It's a complete sentence, ending in a period. It
|
||||
uses a present-tense action verb, "Integrate", rather than "Integrates" or
|
||||
"Integrating".
|
||||
|
||||
The following paragraphs are full prose and explain why and how the change was
|
||||
made. It explains what testing was done and asks specifically for further
|
||||
testing in a more production-like environment.
|
||||
|
||||
The final paragraph indicates that this commit addresses and fixes issue #1755.
|
||||
When you submit your pull request, GitHub will detect and link this reference
|
||||
to the appropriate issue. Once your commit is merged into `upstream/main`, GitHub
|
||||
will automatically close the referenced issue. See [Closing issues via commit
|
||||
messages][github-help-closing-issues] for details.
|
||||
|
||||
Note in particular that GitHub's regular expressions for this feature
|
||||
are sloppy, so phrases like `Partially fixes #1234` will automatically
|
||||
close the issue. Phrases like `Fixes part of #1234` are a good
|
||||
alternative.
|
||||
|
||||
Make as many commits as you need to address the issue or implement your feature.
|
||||
|
||||
## Push your commits to GitHub
|
||||
|
||||
As you're working, it's a good idea to frequently push your changes to GitHub.
|
||||
This ensures your work is backed up should something happen to your local
|
||||
machine and allows others to follow your progress. It also allows you to
|
||||
[work from multiple computers][self-multiple-computers] without losing work.
|
||||
|
||||
Pushing to a feature branch is just like pushing to `main`:
|
||||
|
||||
```console
|
||||
$ git push origin <branch-name>
|
||||
Counting objects: 6, done.
|
||||
Delta compression using up to 4 threads.
|
||||
Compressing objects: 100% (4/4), done.
|
||||
Writing objects: 100% (6/6), 658 bytes | 0 bytes/s, done.
|
||||
Total 6 (delta 3), reused 0 (delta 0)
|
||||
remote: Resolving deltas: 100% (3/3), completed with 1 local objects.
|
||||
To git@github.com:christi3k/zulip.git
|
||||
* [new branch] issue-demo -> issue-demo
|
||||
```
|
||||
|
||||
If you want to see what Git will do without actually performing the push, add
|
||||
the `-n` (dry-run) option: `git push -n origin <branch-name>`. If everything
|
||||
looks good, re-run the push command without `-n`.
|
||||
|
||||
If the feature branch does not already exist on GitHub, it will be created when
|
||||
you push and you'll see `* [new branch]` in the command output.
|
||||
|
||||
## Examine and tidy your commit history
|
||||
|
||||
Examining your commit history prior to submitting your pull request is a good
|
||||
idea. Is it tidy such that each commit represents a minimally coherent idea
|
||||
(see [commit discipline][zulip-rtd-commit-discipline])? Do your commit messages
|
||||
follow [Zulip's style][zulip-rtd-commit-messages]? Will the person reviewing
|
||||
your commit history be able to clearly understand your progression of work?
|
||||
|
||||
On the command line, you can use the `git log` command to display an easy to
|
||||
read list of your commits:
|
||||
|
||||
```console
|
||||
$ git log --all --graph --oneline --decorate
|
||||
|
||||
* 4f8d75d (HEAD -> 1754-docs-add-git-workflow) docs: Add details about configuring Travis CI.
|
||||
* bfb2433 (origin/1754-docs-add-git-workflow) docs: Add section for keeping fork up-to-date to Git Guide.
|
||||
* 4fe10f8 docs: Add sections for creating and configuring fork to Git Guide.
|
||||
* 985116b docs: Add graphic client recs to Git Guide.
|
||||
* 3c40103 docs: Add stubs for remaining Git Guide sections.
|
||||
* fc2c01e docs: Add git guide quickstart.
|
||||
| * f0eaee6 (upstream/main) bug: Fix traceback in get_missed_message_token_from_address().
|
||||
```
|
||||
|
||||
Alternatively, use your graphical client to view the history for your feature branch.
|
||||
|
||||
If you need to update any of your commits, you can do so with an interactive
|
||||
[rebase][github-help-rebase]. Common reasons to use an interactive rebase
|
||||
include:
|
||||
|
||||
- squashing several commits into fewer commits
|
||||
- splitting a single commit into two or more
|
||||
- rewriting one or more commit messages
|
||||
|
||||
There is ample documentation on how to rebase, so we won't go into details
|
||||
here. We recommend starting with GitHub's help article on
|
||||
[rebasing][github-help-rebase] and then consulting Git's documentation for
|
||||
[git-rebase][gitbook-git-rebase] if you need more details.
|
||||
|
||||
If all you need to do is edit the commit message for your last commit, you can
|
||||
do that with `git commit --amend`. See [Git Basics - Undoing
|
||||
Things][gitbook-basics-undoing] for details on this and other useful commands.
|
||||
|
||||
## Force-push changes to GitHub after you've altered your history
|
||||
|
||||
Any time you alter history for commits you have already pushed to GitHub,
|
||||
you'll need to prefix the name of your branch with a `+`. Without this, your
|
||||
updates will be rejected with a message such as:
|
||||
|
||||
```console
|
||||
$ git push origin 1754-docs-add-git-workflow
|
||||
To git@github.com:christi3k/zulip.git
|
||||
! [rejected] 1754-docs-add-git-workflow -> 1754-docs-add-git-workflow (non-fast-forward)
|
||||
error: failed to push some refs to 'git@github.com:christi3k/zulip.git'
|
||||
hint: Updates were rejected because the tip of your current branch is behind
|
||||
hint: its remote counterpart. Integrate the remote changes (e.g.,
|
||||
hint: 'git pull ...') before pushing again.
|
||||
hint: See the 'Note about fast-forwards' in 'git push --help' for details.
|
||||
```
|
||||
|
||||
Re-running the command with `+<branch>` allows the push to continue by
|
||||
re-writing the history for the remote repository:
|
||||
|
||||
```console
|
||||
$ git push origin +1754-docs-add-git-workflow
|
||||
Counting objects: 12, done.
|
||||
Delta compression using up to 4 threads.
|
||||
Compressing objects: 100% (12/12), done.
|
||||
Writing objects: 100% (12/12), 3.71 KiB | 0 bytes/s, done.
|
||||
Total 12 (delta 8), reused 0 (delta 0)
|
||||
remote: Resolving deltas: 100% (8/8), completed with 2 local objects.
|
||||
To git@github.com:christi3k/zulip.git
|
||||
+ 2d49e2d...bfb2433 1754-docs-add-git-workflow -> 1754-docs-add-git-workflow (forced update)
|
||||
```
|
||||
|
||||
This is perfectly okay to do on your own feature branches, especially if you're
|
||||
the only one making changes to the branch. If others are working along with
|
||||
you, they might run into complications when they retrieve your changes because
|
||||
anyone who has based their changes off a branch you rebase will have to do a
|
||||
complicated rebase.
|
||||
|
||||
[gitbook-add]: https://git-scm.com/docs/git-add
|
||||
[gitbook-basics-undoing]: https://git-scm.com/book/en/v2/Git-Basics-Undoing-Things
|
||||
[gitbook-fetch]: https://git-scm.com/docs/git-fetch
|
||||
[gitbook-git-branch]: https://git-scm.com/docs/git-branch
|
||||
[gitbook-git-pull]: https://git-scm.com/docs/git-pull
|
||||
[gitbook-git-rebase]: https://git-scm.com/docs/git-rebase
|
||||
[gitbook-git-status]: https://git-scm.com/docs/git-status
|
||||
[gitbook-other-envs-bash]: https://git-scm.com/book/en/v2/Appendix-A%3A-Git-in-Other-Environments-Git-in-Bash
|
||||
[gitbook-other-envs-zsh]: https://git-scm.com/book/en/v2/Appendix-A%3A-Git-in-Other-Environments-Git-in-Zsh
|
||||
[gitbook-rm]: https://git-scm.com/docs/git-rm
|
||||
[github-help-closing-issues]: https://help.github.com/en/articles/closing-issues-via-commit-messages
|
||||
[github-help-push]: https://help.github.com/en/articles/pushing-to-a-remote
|
||||
[github-help-rebase]: https://help.github.com/en/articles/using-git-rebase
|
||||
[github-help-sync-fork]: https://help.github.com/en/articles/syncing-a-fork
|
||||
[how-git-is-different]: the-git-difference.md
|
||||
[self-multiple-computers]: troubleshooting.md#working-from-multiple-computers
|
||||
[zulip-git-guide-up-to-date]: #keep-your-fork-up-to-date
|
||||
[zulip-rtd-commit-discipline]: ../contributing/commit-discipline.md
|
||||
[zulip-rtd-commit-messages]: ../contributing/commit-discipline.md
|
||||
50
docs/git/working-copies.md
Normal file
50
docs/git/working-copies.md
Normal file
@@ -0,0 +1,50 @@
|
||||
# Working copies
|
||||
|
||||
When you work on Zulip code, there are three copies of the Zulip Git
|
||||
repository that you are generally concerned with:
|
||||
|
||||
- The `upstream` remote. This is the [official Zulip
|
||||
repository](https://github.com/zulip/zulip) on GitHub. You probably
|
||||
don't have write access to this repository.
|
||||
- The **origin** remote: Your personal remote repository on GitHub.
|
||||
You'll use this to share your code and create [pull requests](pull-requests.md).
|
||||
- local copy: This lives on your laptop or your remote dev instance,
|
||||
and is what you'll use to make changes and create commits.
|
||||
|
||||
When you work on Zulip code, you will end up moving code between
|
||||
the various working copies.
|
||||
|
||||
## Workflows
|
||||
|
||||
Sometimes you need to get commits. Here are some scenarios:
|
||||
|
||||
- You may fork the official Zulip repository to your GitHub fork.
|
||||
- You may fetch commits from the official Zulip repository to your local copy.
|
||||
- You occasionally may fetch commits from your forked copy.
|
||||
|
||||
Sometimes you want to publish commits. Here are some scenarios:
|
||||
|
||||
- You push code from your local copy to your GitHub fork. (You usually
|
||||
want to put the commit on a feature branch.)
|
||||
- You submit a PR to the official Zulip repo.
|
||||
|
||||
Finally, the Zulip core team will occasionally want your changes!
|
||||
|
||||
- The Zulip core team can accept your changes and add them to
|
||||
the official repo, usually on the `main` branch.
|
||||
|
||||
## Relevant Git commands
|
||||
|
||||
The following commands are useful for moving commits between
|
||||
working copies:
|
||||
|
||||
- `git fetch`: This grabs code from another repository to your local
|
||||
copy. (Defaults to fetching from your default remote, `origin`).
|
||||
- `git fetch upstream`: This grabs code from the upstream repository to your local copy.
|
||||
- `git push`: This pushes code from your local repository to one of the remotes.
|
||||
- `git remote`: This helps you configure short names for remotes.
|
||||
- `git pull`: This pulls code, but by default creates a merge commit
|
||||
(which you definitely don't want). However, if you've followed our
|
||||
[cloning documentation](cloning.md), this will do
|
||||
`git pull --rebase` instead, which is the only mode you'll want to
|
||||
use when working on Zulip.
|
||||
180
docs/git/zulip-tools.md
Normal file
180
docs/git/zulip-tools.md
Normal file
@@ -0,0 +1,180 @@
|
||||
# Zulip-specific tools
|
||||
|
||||
This article documents several useful tools that can save you a lot of
|
||||
time when working with Git on the Zulip project.
|
||||
|
||||
## Set up Git repo script
|
||||
|
||||
**Extremely useful**. In the `tools` directory of
|
||||
[zulip/zulip][github-zulip-zulip] you'll find a bash script
|
||||
`setup-git-repo`. This script installs a pre-commit hook, which will
|
||||
run each time you `git commit` to automatically run
|
||||
[Zulip's linter suite](../testing/linters.md) on just the files that
|
||||
the commit modifies (which is really fast!). The hook passes no matter
|
||||
the result of the linter, but you should still pay attention to any
|
||||
notices or warnings it displays.
|
||||
|
||||
It's simple to use. Make sure you're in the clone of zulip and run the following:
|
||||
|
||||
```console
|
||||
$ ./tools/setup-git-repo
|
||||
```
|
||||
|
||||
The script doesn't produce any output if successful. To check that the hook has
|
||||
been installed, print a directory listing for `.git/hooks` and you should see
|
||||
something similar to:
|
||||
|
||||
```console
|
||||
$ ls -l .git/hooks
|
||||
pre-commit -> ../../tools/pre-commit
|
||||
```
|
||||
|
||||
## Configure continuous integration for your Zulip fork
|
||||
|
||||
You might also wish to [configure continuous integration for your fork][zulip-git-guide-ci].
|
||||
|
||||
## Reset to pull request
|
||||
|
||||
`tools/reset-to-pull-request` is a short-cut for [checking out a pull request
|
||||
locally][zulip-git-guide-fetch-pr]. It works slightly differently from the method
|
||||
described above in that it does not create a branch for the pull request
|
||||
checkout.
|
||||
|
||||
**This tool checks for uncommitted changes, but it will move the
|
||||
current branch using `git reset --hard`. Use with caution.**
|
||||
|
||||
First, make sure you are working in a branch you want to move (in this
|
||||
example, we'll use the local `main` branch). Then run the script
|
||||
with the ID number of the pull request as the first argument.
|
||||
|
||||
```console
|
||||
$ git checkout main
|
||||
Switched to branch 'main'
|
||||
Your branch is up-to-date with 'origin/main'.
|
||||
|
||||
$ ./tools/reset-to-pull-request 1900
|
||||
+ request_id=1900
|
||||
+ git fetch upstream pull/1900/head
|
||||
remote: Counting objects: 159, done.
|
||||
remote: Compressing objects: 100% (17/17), done.
|
||||
remote: Total 159 (delta 94), reused 91 (delta 91), pack-reused 51
|
||||
Receiving objects: 100% (159/159), 55.57 KiB | 0 bytes/s, done.
|
||||
Resolving deltas: 100% (113/113), completed with 54 local objects.
|
||||
From https://github.com/zulip/zulip
|
||||
* branch refs/pull/1900/head -> FETCH_HEAD
|
||||
+ git reset --hard FETCH_HEAD
|
||||
HEAD is now at 2bcd1d8 troubleshooting tip about provisioning
|
||||
```
|
||||
|
||||
## Fetch a pull request and rebase
|
||||
|
||||
`tools/fetch-rebase-pull-request` is a short-cut for [checking out a pull
|
||||
request locally][zulip-git-guide-fetch-pr] in its own branch and then updating it with any
|
||||
changes from `upstream/main` with `git rebase`.
|
||||
|
||||
Run the script with the ID number of the pull request as the first argument.
|
||||
|
||||
```console
|
||||
$ tools/fetch-rebase-pull-request 1913
|
||||
+ request_id=1913
|
||||
+ git fetch upstream pull/1913/head
|
||||
remote: Counting objects: 4, done.
|
||||
remote: Compressing objects: 100% (4/4), done.
|
||||
remote: Total 4 (delta 0), reused 0 (delta 0), pack-reused 0
|
||||
Unpacking objects: 100% (4/4), done.
|
||||
From https://github.com/zulip/zulip
|
||||
* branch refs/pull/1913/head -> FETCH_HEAD
|
||||
+ git checkout upstream/main -b review-1913
|
||||
Branch review-1913 set up to track remote branch main from upstream.
|
||||
Switched to a new branch 'review-1913'
|
||||
+ git reset --hard FETCH_HEAD
|
||||
HEAD is now at 99aa2bf Add provision.py fails issue in common errors
|
||||
+ git pull --rebase
|
||||
Current branch review-1913 is up to date.
|
||||
```
|
||||
|
||||
## Fetch a pull request without rebasing
|
||||
|
||||
`tools/fetch-pull-request` is a similar to `tools/fetch-rebase-pull-request`, but
|
||||
it does not rebase the pull request against `upstream/main`, thereby getting
|
||||
exactly the same repository state as the commit author had.
|
||||
|
||||
Run the script with the ID number of the pull request as the first argument.
|
||||
|
||||
```console
|
||||
$ tools/fetch-pull-request 5156
|
||||
+ git diff-index --quiet HEAD
|
||||
+ request_id=5156
|
||||
+ remote=upstream
|
||||
+ git fetch upstream pull/5156/head
|
||||
From https://github.com/zulip/zulip
|
||||
* branch refs/pull/5156/head -> FETCH_HEAD
|
||||
+ git checkout -B review-original-5156
|
||||
Switched to a new branch 'review-original-5156'
|
||||
+ git reset --hard FETCH_HEAD
|
||||
HEAD is now at 5a1e982 tools: Update clean-branches to clean review branches.
|
||||
```
|
||||
|
||||
## Push to a pull request
|
||||
|
||||
`tools/push-to-pull-request` is primarily useful for maintainers who
|
||||
are merging other users' commits into a Zulip repository. After doing
|
||||
`reset-to-pull-request` or `fetch-pull-request` and making some
|
||||
changes, you can push a branch back to a pull request with, for example,
|
||||
`tools/push-to-pull-request 1234`. This is useful for a few things:
|
||||
|
||||
- Getting CI to run and enabling you to use the GitHub "Merge" buttons
|
||||
to merge a PR after you make some corrections to a PR, without
|
||||
waiting for an extra round trip with the PR author.
|
||||
- For commits that aren't ready to merge yet, communicating clearly
|
||||
any changes you'd like to see happen that are easier for you to
|
||||
explain by just editing the code than in words.
|
||||
- Saving a contributor from needing to duplicate any rebase work that
|
||||
you did as part of integrating parts of the PR.
|
||||
|
||||
You'll likely want to comment on the PR after doing so, to ensure that
|
||||
the original contributor knows to pull your changes rather than
|
||||
accidentally overwriting them with a force push when they make their
|
||||
next batch of changes.
|
||||
|
||||
Note that in order to do this you need permission to do such a push,
|
||||
which GitHub offers by default to users with write access to the
|
||||
repository. For multiple developers collaborating on a PR, you can
|
||||
achieve this by granting other users permission to write to your fork.
|
||||
|
||||
## Delete unimportant branches
|
||||
|
||||
`tools/clean-branches` is a shell script that removes branches that are either:
|
||||
|
||||
1. Local branches that are ancestors of `origin/main`.
|
||||
2. Branches in origin that are ancestors of `origin/main` and named like `$USER-*`.
|
||||
3. Review branches created by `tools/fetch-rebase-pull-request` and `tools/fetch-pull-request`.
|
||||
|
||||
First, make sure you are working in branch `main`. Then run the script without any
|
||||
arguments for default behavior. Since removing review branches can inadvertently remove any
|
||||
feature branches whose names are like `review-*`, it is not done by default. To
|
||||
use it, run `tools/clean-branches --reviews`.
|
||||
|
||||
```console
|
||||
$ tools/clean-branches --reviews
|
||||
Deleting local branch review-original-5156 (was 5a1e982)
|
||||
```
|
||||
|
||||
## Merge conflict on `pnpm-lock.yaml` file
|
||||
|
||||
If there is a merge conflict on `pnpm-lock.yaml`, pnpm should be run to
|
||||
regenerate the file. _Important:_ don't delete the `pnpm-lock.yaml` file. Check out the
|
||||
latest one from `origin/main` so that pnpm knows the previous asset versions.
|
||||
|
||||
Run the following commands
|
||||
|
||||
```bash
|
||||
git checkout origin/main -- pnpm-lock.yaml
|
||||
pnpm install
|
||||
git add pnpm-lock.yaml
|
||||
git rebase --continue
|
||||
```
|
||||
|
||||
[github-zulip-zulip]: https://github.com/zulip/zulip/
|
||||
[zulip-git-guide-fetch-pr]: collaborate.md#check-out-a-pull-request-locally
|
||||
[zulip-git-guide-ci]: cloning.md#step-3-configure-continuous-integration-for-your-fork
|
||||
Reference in New Issue
Block a user