{"action":"created","comment":{"url":"https://api.github.com/repos/zulip/zulip/pulls/comments/82946422","pull_request_review_id":3815296,"id":82946422,"diff_hunk":"@@ -0,0 +1,1052 @@\n+# Git Workflow Guide\n+\n+## Quickstart: How Zulip uses Git and Github\n+\n+This quick start provides a brief overview of how Zulip uses Git and Github.\n+\n+Those who are familiar with Git and GitHub should be able to start contributing with these details in mind:\n+\n+- 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 work-in-progress (WIP) pull request. *We encourage you to submit WIP pull requests early and often.*\n+\n+- 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][github-rebase-pr].\n+\n+- 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).\n+\n+- We provide **many tools to help you submit quality code.** These include [linters][zulip-rtd-lint-tools], [tests][zulip-rtd-testing], continuous integration with [TracisCI][travis-ci], and [mypy][zulip-rtd-mypy].\n+\n+***\n+\n+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.\n+\n+Below you'll find tips as well as more detailed walkthroughs of the most common contribution-related scenarios.\n+\n+## Get setup\n+\n+If you're already using Git, have a client you like, and a GitHub account, you can skip this section. Otherwise, read on!\n+\n+### Install and configure Git, join GitHub\n+\n+If you're not already using Git, you might need to [install][gitbook-install] and [configure][gitbook-setup] it.\n+\n+You'll also need a GitHub account, which you can sign up for [here][github-join]. We also 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].\n+\n+If you plan on using Git from the command line, the following tips can make your experience better:\n+\n+- Install the command auto-completion and/or git-prompt plugins available for [Bash][gitbook-other-envs-bash] and [Zsh][gitbook-other-envs-zsh].\n+- Configure [Git aliases][gitbook-aliases] for commands you'll use often.\n+\n+### Get a graphical client\n+\n+Even if you're comfortable using git on the command line, having a graphic client can be useful for viewing commit history.\n+\n+If you don't already have one installed, here are some suggestions:\n+\n+- macOS: [GitX-dev][gitgui-gitxdev]\n+- Ubuntu/Linux: [git-cola][gitgui-gitcola], [gitg][gitgui-gitg]\n+- Windows: [SourceTree][gitgui-sourcetree]\n+\n+If none of those are to your liking, see try [one of these][gitbook-guis].\n+\n+### Understand how Git is different\n+\n+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.\n+\n+Here are the top things to know:\n+\n+- **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 change, Git creates a link to the identical file rather than storing it again.\n+\n+- **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, commiting, 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`.\n+\n+- **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 freqently push your commits to your remote repository.\n+\n+- **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.\n+\n+- **Git stores all data as objects, of which there are four types:** blob (file), tree (directory), commit (revision), and tag. Each of these objects has a unique hash, the SHA-1 has 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**.\n+\n+- **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` is the *working tree*.\n+\n+- **Files tracked with Git have possible three states: committed, modified, and stagaed.** 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.\n+\n+- **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`.\n+\n+### Important Git terms\n+\n+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*.\n+\n+#### branch\n+A \"branch\" is an active line of development. The most recent commit\n+on a branch is referred to as the tip of that branch. The tip of\n+the branch is referenced by a branch head, which moves forward as\n+additional development is done on the branch. A single Git\n+repository can track an arbitrary number of branches, but your\n+working tree is associated with just one of them (the \"current\" or\n+\"checked out\" branch), and HEAD points to that branch.\n+\n+#### cache\n+Obsolete for: index\n+\n+#### checkout\n+The action of updating all or part of the working tree with a tree\n+object or blob from the object database, and updating the index and\n+HEAD if the whole working tree has been pointed at a new branch.\n+\n+#### commit\n+As a noun: A single point in the Git history; the entire history of\n+a project is represented as a set of interrelated commits. The word\n+\"commit\" is often used by Git in the same places other revision\n+control systems use the words \"revision\" or \"version\". Also used as\n+a short hand for commit object.\n+\n+As a verb: The action of storing a new snapshot of the project's\n+state in the Git history, by creating a new commit representing the\n+current state of the index and advancing HEAD to point at the new\n+\n+#### fast-forward\n+A fast-forward is a special type of merge where you have a revision\n+and you are \"merging\" another branch's changes that happen to be a\n+descendant of what you have. In such these cases, you do not make a\n+new mergecommit but instead just update to his revision. This will\n+happen frequently on a remote-tracking branch of a remote\n+repository.\n+\n+#### fetch\n+Fetching a branch means to get the branch's head ref from a remote\n+repository, to find out which objects are missing from the local\n+object database, and to get them, too. See also git-fetch(1).\n+\n+#### hash\n+In Git's context, synonym for object name.\n+\n+#### head\n+A named reference to the commit at the tip of a branch. Heads are\n+stored in a file in $GIT_DIR/refs/heads/ directory, except when\n+using packed refs. (See git-pack-refs(1).)\n+\n+#### HEAD\n+The current branch. In more detail: Your working tree is normally\n+derived from the state of the tree referred to by HEAD. HEAD is a\n+reference to one of the heads in your repository, except when using\n+a detached HEAD, in which case it directly references an arbitrary\n+commit.\n+\n+#### index\n+A collection of files with stat information, whose contents are\n+stored as objects. The index is a stored version of your working\n+tree. Truth be told, it can also contain a second, and even a third\n+version of a working tree, which are used when merging.\n+\n+#### pull\n+Pulling a branch means to fetch it and merge it. See also git-\n+pull(1).\n+\n+#### push\n+Pushing a branch means to get the branch's head ref from a remote\n+repository, find out if it is a direct ancestor to the branch's\n+local head ref, and in that case, putting all objects, which are\n+reachable from the local head ref, and which are missing from the\n+remote repository, into the remote object database, and updating\n+the remote head ref. If the remote head is not an ancestor to the\n+local head, the push fails.\n+\n+#### rebase\n+To reapply a series of changes from a branch to a different base,\n+and reset the head of that branch to the result.\n+\n+## Prepare to contribute\n+\n+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.\n+\n+### Step 1a: Create your fork and clone to your machine\n+\n+The following steps you'll only need to do the first time you setup 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.\n+\n+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].\n+\n+Next, clone your fork to your local machine:\n+\n+```\n+$ git clone https://github.com/YOUR_USERNAME/zulip.git\n+Cloning into 'zulip'\n+remote: Counting objects: 86768, done.\n+remote: Compressing objects: 100% (15/15), done.\n+remote: Total 86768 (delta 5), reused 1 (delta 1), pack-reused 86752\n+Receiving objects: 100% (86768/86768), 112.96 MiB | 523.00 KiB/s, done.\n+Resolving deltas: 100% (61106/61106), done.\n+Checking connectivity... done.\n+```\n+\n+### Step 1b: Connect your fork to Zulip upstream\n+\n+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.\n+\n+First, show the currently configured remote repository:\n+\n+```\n+$ git remote -v\n+origin  git@github.com:YOUR_USERNAME/zulip.git (fetch)\n+origin  git@github.com:YOUR_USERNAME/zulip.git (push)\n+```\n+\n+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`:\n+\n+```\n+origin   https://github.com/koehlerwtf/zulip.git (fetch)\n+origin   https://github.com/koehlerwtf/zulip.git (push)\n+zulip    https://github.com/zulip/zulip.git (fetch)\n+zulip    https://github.com/zulip/zulip.git (push)\n+```\n+\n+If your client hasn't automatically configured a remote for zulip/zulip, you'll need to with:\n+\n+```\n+$ git remote add upstream https://github.com/zulip/zulip.git\n+```\n+\n+Finally, confirm that the new remoate repository, upstream, has been configured:\n+\n+```\n+$ git remote -v\n+origin  git@github.com:YOUR_USERNAME/zulip.git (fetch)\n+origin  git@github.com:YOUR_USERNAME/zulip.git (push)\n+upstream https://github.com/zulip/zulip.git (fetch)\n+upstream https://github.com/zulip/zulip.git (push)\n+```\n+\n+### Step 2: Setup the Zulip dev environment\n+\n+If you haven't already, now is a good time to install the Zulip dev 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].\n+\n+### Step 3: Configure Travis CI (continuos integration)\n+\n+This step is optional, but recommended.\n+\n+Zulip Server is configured to use [Travis CI][travis-ci] to test and create builds upon each new commit and pull request. Travis CI is free for open source projects and it's easy to configure for your own fork of Zulip. Doing so enables you to get test results and build notifications for your in-progress work.\n+\n+First, sign in to [Travis CI][travis-ci] with your GitHub account and authorize Travis CI to access your GitHub account and repositories. Once you've done this, Travis CI will fetch your repository information and display it on your [profile page][travis-ci-profile]. From there you can enable integration with Zulip. ([See screencast](_static/zulip-travisci.gif).)\n+\n+## Contribute\n+\n+### Know what branch you're working on\n+\n+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.\n+\n+One way is with [git status][gitbook-git-status]:\n+\n+```\n+$ git status\n+On branch issue-demo\n+nothing to commit, working directory clean\n+```\n+\n+Another is with [git branch][gitbook-git-branch] which will display all local branches, with a star next to the current branch:\n+\n+```\n+$ git branch\n+* issue-demo\n+  master\n+```\n+\n+To see even more information about your branches, including remote branches, use `git branch -vva`:\n+\n+```\n+$ git branch -vva\n+* issue-123                 517468b troubleshooting tip about provisioning\n+  master                    f0eaee6 [origin/master] bug: Fix traceback in get_missed_message_token_from_address().\n+  remotes/origin/HEAD       -> origin/master\n+  remotes/origin/issue-1234 4aeccb7 Another test commit, with longer message.\n+  remotes/origin/master     f0eaee6 bug: Fix traceback in get_missed_message_token_from_address().\n+  remotes/upstream/master   dbeab6a Optimize checks of test database state by moving into Python.\n+```\n+\n+You can also configure [Bash][gitbook-other-envs-bash] and [Zsh][gitbook-other-envs-zsh] to display the current branch in your prompt.\n+\n+### Keep your fork up to date\n+\n+You'll want to [keep your fork][github-help-sync-fork] up-to-date with changes from Zulip's main repositories.\n+\n+**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 that using `git pull`, which by default is a shortcut for `git fetch && git merge FECH_HEAD` ([docs][gitbook-git-pull]), you should use `git fetch` and then `git rebase`.\n+\n+First, [fetch][gitbook-fetch] changes from Zulip's upstream repository you configured in the step above:\n+\n+```\n+$ git fetch upstream\n+```\n+\n+Next, checkout your `master` branch and [rebase][gitbook-git-rebase] it on top of `upstream/master`:\n+\n+```\n+$ git checkout master\n+Switched to branch 'master'\n+\n+$ git rebase upstream/master\n+```\n+\n+This will rollback any changes you've made to master, update it from `upstream/master`, and then re-apply your changes. Rebasing keeps the commit history clean and readable.\n+\n+When you're ready, [push your changes][github-help-push] to your remote fork. Make sure you're in branch `master` and the run `git push`:\n+\n+```\n+$ git checkout master\n+$ git push origin master\n+```\n+\n+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 `master`:\n+\n+```\n+$ git checkout feature-branch\n+Switched to branch 'feature-branch'\n+\n+$ git rebase upstream/master\n+\n+$ git push origin feature-branch\n+```\n+\n+### Work on a feature branch\n+\n+One way to keep your work oraganized is to create a branch for each issue or feature.\n+\n+First, make sure your master branch is up-to-date with Zulip upstream ([see how][self-keep-up-to-date]).\n+\n+Next, from your master branch, create a new tracking branch, providing a descriptive name for your feature branch:\n+\n+```\n+$ git checkout master\n+Switched to branch 'master'\n+\n+$ git checkout -b issue-1755-fail2ban\n+Switched to a new branch 'issue-1755-fail2ban'\n+```\n+\n+Now you're ready to work on the issue or feature.\n+\n+### Run linters and tests locally\n+\n+In addition to having Travis run tests and linters each time you push a new commit, you can also run them locally. See [testing](testing.html) for details.\n+\n+### Stage changes\n+\n+Git includes the concept of a *staging* area for changes you intended to commit. To prepare a commit, you 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.\n+\n+#### Get status of working directory\n+\n+To see what files in the working directory have changes that have not been staged, use `git status`.\n+\n+If you have no changes in the working directory, you'll see something like this:\n+\n+```\n+$ git status\n+On branch issue-123\n+nothing to commit, working directory clean\n+```\n+\n+If you have unstaged changes, you'll see something like this:\n+\n+```\n+On branch issue-123\n+Untracked files:\n+  (use \"git add <file>...\" to include in what will be committed)\n+\n+        newfile.py\n+\n+nothing added to commit but untracked files present (use \"git add\" to track)\n+```\n+\n+#### Stage additions with git add\n+\n+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.\n+\n+Continuing our example from above, after we run `git add newfile.py`, we'll see the following from `git status`:\n+\n+```\n+On branch issue-123\n+Changes to be committed:\n+  (use \"git reset HEAD <file>...\" to unstage)\n+\n+        new file:   newfile.py\n+```\n+\n+If you want to add all changes in the working directory, use `git add -A` ([documentation][gitbook-add]).\n+\n+You can also stage changes using your graphic git client.\n+\n+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:\n+\n+```\n+$ git add test3.txt\n+On branch issue-1234\n+Changes to be committed:\n+  (use \"git reset HEAD <file>...\" to unstage)\n+\n+        new file:   test3.txt\n+\n+$ git reset HEAD test3.txt\n+$ git status\n+On branch issue-1234\n+Untracked files:\n+  (use \"git add <file>...\" to include in what will be committed)\n+\n+        test3.txt\n+\n+nothing added to commit but untracked files present (use \"git add\" to track)\n+```\n+\n+#### Stage deletions with git rm\n+\n+To remove existing files from your repo, 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.\n+\n+To stage a file for deletion and **remove** it from your working directory, use `git rm <filename>`:\n+\n+```\n+$ git rm test.txt\n+rm 'test.txt'\n+\n+$ git status\n+On branch issue-1234\n+Changes to be committed:\n+  (use \"git reset HEAD <file>...\" to unstage)\n+\n+        deleted:    test.txt\n+\n+$ ls test.txt\n+ls: No such file or directory\n+```\n+\n+To stage a file for deletion and **keep** it in your working directory, use `git rm --cached <filename>`:\n+\n+```\n+$ git rm --cached test2.txt\n+rm 'test2.txt'\n+\n+$ git status\n+On branch issue-1234\n+Changes to be committed:\n+  (use \"git reset HEAD <file>...\" to unstage)\n+\n+        deleted:    test2.txt\n+\n+$ ls test2.txt\n+test2.txt\n+```\n+\n+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>`:\n+\n+```\n+$ git reset HEAD test2.txt\n+```\n+\n+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.\n+\n+### Commit changes\n+\n+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.\n+\n+Here's an example of commiting with the `-m` for a one-line commit message:\n+\n+```\n+$ git commit -m \"Add a test commit for docs.\"\n+[issue-123 173e17a] Add a test commit for docs.\n+ 1 file changed, 1 insertion(+)\n+ create mode 100644 newfile.py\n+```\n+\n+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.\n+\n+How long your commit message should be depends on where you are in your work. Use 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.\n+\n+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.\n+\n+Here's an example of a longer commit message that will be used for a pull request:\n+\n+```\n+Integrate Fail2Ban.\n+\n+Updates Zulip logging to put an unambiguous entry into the logs such\n+that fail2ban can be configured to look for these entries.\n+\n+Tested on my local Ubuntu dev server, but would appreciate someone\n+testing on a production install with more users.\n+\n+Fixes #1755.\n+```\n+\n+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\".\n+\n+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.\n+\n+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.\n+\n+Make as many commits as you need to to address the issue or implement your feature.\n+\n+### Push your commits to Github\n+\n+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.\n+\n+Pushing to a feature branch is just like pushing to master:\n+\n+```\n+$ git push origin <branch-name>\n+Counting objects: 6, done.\n+Delta compression using up to 4 threads.\n+Compressing objects: 100% (4/4), done.\n+Writing objects: 100% (6/6), 658 bytes | 0 bytes/s, done.\n+Total 6 (delta 3), reused 0 (delta 0)\n+remote: Resolving deltas: 100% (3/3), completed with 1 local objects.\n+To git@github.com:christi3k/zulip.git\n+ * [new branch]      issue-demo -> issue-demo\n+```\n+\n+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`.\n+\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.\n+\n+### Examine and tidy your commit history\n+\n+Examining your commit history prior to submitting your pull request is a good idea. Is it tidy such that each commit represents a minally 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?\n+\n+On the command line, you can use the `git log` command to display an easy to read list of your commits:\n+\n+```\n+$ git log --all --graph --oneline --decorate\n+\n+* 4f8d75d (HEAD -> 1754-docs-add-git-workflow) docs: Add details about configuring Travis CI.\n+* bfb2433 (origin/1754-docs-add-git-workflow) docs: Add section for keeping fork up-to-date to Git Guide.\n+* 4fe10f8 docs: Add sections for creating and configuring fork to Git Guide.\n+* 985116b docs: Add graphic client recs to Git Guide.\n+* 3c40103 docs: Add stubs for remaining Git Guide sections.\n+* fc2c01e docs: Add git guide quickstart.\n+| * f0eaee6 (upstream/master) bug: Fix traceback in get_missed_message_token_from_address().\n+```\n+\n+Alternatively, use your graphical client to view the history for your feature branch.\n+\n+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:\n+\n+- squashing several commits into fewer commits\n+- spliting a single commit into two or more\n+- rewriting one or more commit messages\n+\n+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.\n+\n+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.\n+\n+### Force-push changes to GitHub after you've altered your history\n+\n+Any time you alter history for commits you have already pushed to GitHub, you'll need to push with the `--force` option. Without this option, your updates will be rejected with a message such as:\n+\n+```\n+$ git push origin 1754-docs-add-git-workflow\n+To git@github.com:christi3k/zulip.git\n+ ! [rejected] 1754-docs-add-git-workflow -> 1754-docs-add-git-workflow (non-fast-forward)\n+error: failed to push some refs to 'git@github.com:christi3k/zulip.git'\n+hint: Updates were rejected because the tip of your current branch is behind\n+hint: its remote counterpart. Integrate the remote changes (e.g.\n+hint: 'git pull ...') before pushing again.\n+hint: See the 'Note about fast-forwards' in 'git push --help' for details.\n+\n+```\n+\n+Re-running the command with `--force` allows the push to continue by re-writing the history for the remote repository:\n+\n+```\n+$ git push --force origin 1754-docs-add-git-workflow\n+Counting objects: 12, done.\n+Delta compression using up to 4 threads.\n+Compressing objects: 100% (12/12), done.\n+Writing objects: 100% (12/12), 3.71 KiB | 0 bytes/s, done.\n+Total 12 (delta 8), reused 0 (delta 0)\n+remote: Resolving deltas: 100% (8/8), completed with 2 local objects.\n+To git@github.com:christi3k/zulip.git\n+ + 2d49e2d...bfb2433 1754-docs-add-git-workflow -> 1754-docs-add-git-workflow (forced update)\n+\n+```\n+\n+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\n+\n+## Submit your work\n+\n+When you're ready for feedback, submit a pull request. At Zulip we recommend submitting work-in-progress pull requests early and often. This allows you to get feedback and help with your bugfix or feature. Prefix work-in-progress pull requests with **[WIP]**.\n+\n+### Create a pull request\n+\n+Pull requests are a feature specific to GitHub. They provide a simpler, 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.\n+\n+If you're unfamiliar with how to create a pull request, checkout 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.\n+\n+#### Step 1: Update your branch with git rebase\n+\n+Before you create your pull request, it's a good idea to update your branch with any commits made to upstream/master since you created the branch or last updated it. This no only helps those who will review your code, but ensures you're working against the most recent code.\n+\n+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][self-keep-up-to-date] for details.\n+\n+Here's an example (you would replace *issue-123* with the name of your feature branch):\n+\n+```\n+$ git checkout issue123\n+Switched to branch 'issue-123'\n+\n+$ git fetch upstream\n+remote: Counting objects: 69, done.\n+remote: Compressing objects: 100% (23/23), done.\n+remote: Total 69 (delta 49), reused 39 (delta 39), pack-reused 7\n+Unpacking objects: 100% (69/69), done.\n+From https://github.com/zulip/zulip\n+   69fa600..43e21f6  master     -> upstream/master\n+\n+$ git rebase upstream/master\n+\n+First, rewinding head to replay your work on top of it...\n+Applying: troubleshooting tip about provisioning\n+```\n+\n+#### Step 2: Push your updated branch to your remote fork\n+\n+Once you've updated your local feature branch, push the changes to GitHub:\n+\n+```\n+$ git push origin issue-123\n+Counting objects: 6, done.\n+Delta compression using up to 4 threads.\n+Compressing objects: 100% (4/4), done.\n+Writing objects: 100% (6/6), 658 bytes | 0 bytes/s, done.\n+Total 6 (delta 3), reused 0 (delta 0)\n+remote: Resolving deltas: 100% (3/3), completed with 1 local objects.\n+To git@github.com:christi3k/zulip.git\n+ + 2d49e2d...bfb2433 issue-123 -> issue-123\n+```\n+\n+If your push is rejected with error **failed to push some refs** then you need to use the `--force` option when you push:\n+\n+```\n+$ git push --force origin issue-123\n+Counting objects: 6, done.\n+Delta compression using up to 4 threads.\n+Compressing objects: 100% (4/4), done.\n+Writing objects: 100% (6/6), 658 bytes | 0 bytes/s, done.\n+Total 6 (delta 3), reused 0 (delta 0)\n+remote: Resolving deltas: 100% (3/3), completed with 1 local objects.\n+To git@github.com:christi3k/zulip.git\n+ + 2d49e2d...bfb2433 issue-123 -> issue-123 (forced update)\n+```\n+\n+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.\n+\n+#### Step 3: Open the pull request\n+\n+If you've never created a pull request or need a refresher, take a look at GitHub's article [creating a pull request from a fork][github-help-create-pr-fork]. We'll briefly review the process here.\n+\n+The first step in creating a pull request is to use your web browser to navigate to your fork of Zulip. Sign in to GitHub if you haven't already.\n+\n+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.\n+\n+Alternatively, if you've recently pushed to your fork, you will see a green **Compare & pull request** button.\n+\n+You'll see the *Open a pull request* page:\n+\n+![images-create-pr]\n+\n+Provide a **title** and first comment for your pull request. When ready, click gree **Create pull request** to submit the pull request.\n+\n+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.\n+\n+### Update your pull request\n+\n+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.\n+\n+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][self-keep-up-to-date] for details. You might also find this excellent article [How to Rebase a Pull Request][edx-howto-rebase-pr] helpful.\n+\n+## Collaborate\n+\n+### Fetch another contributor's branch\n+\n+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.\n+\n+```\n+$ git remote add <username> https://github.com/<username>/zulip.git\n+$ git fetch <username>\n+```\n+\n+Now you can checkout 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.\n+\n+```\n+$ git checkout -b <username>-<branchname>\n+```\n+\n+### Checkout a pull request locally\n+\n+Just as you can checkout any user's branch locally, you can also checkout 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.\n+\n+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:\n+\n+```\n+$ git fetch upstream pull/ID/head:BRANCHNAME\n+```\n+\n+Now switch to the branch:\n+\n+```\n+$ git checkout BRANCHNAME\n+```\n+\n+Now you work on this branch as you would any other.\n+\n+## Review changes\n+\n+### Changes on (local) working tree\n+\n+Display changes between index and working tree (what is not yet staged for commit):\n+\n+```\n+$ git diff\n+```\n+\n+Display changes between index and last commit (what you have staged for commit):\n+\n+```\n+$ git diff --cached\n+```\n+\n+Display changes in working tree since last commit (changes that are staged as well as ones that are not):\n+\n+```\n+$ git diff HEAD\n+```\n+\n+### Changes within branches\n+\n+Use any git-ref to compare changes between two commits on the current branch.\n+\n+Display changes between commit before last and last commit:\n+\n+```\n+$ git diff HEAD^ HEAD\n+```\n+\n+Display changes between two commits using their hashes:\n+\n+```\n+$ git diff e2f404c 7977169\n+```\n+\n+### Changes between branches\n+\n+Display changes between tip of topic branch and tip of master branch:\n+\n+```\n+$ git diff topic master\n+```\n+\n+Display changes that have occured on master branch since topic branch was created:\n+\n+```\n+$ git diff topic...master\n+```\n+\n+## Get out of trouble\n+\n+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 freqently push your commits to your remote repository.\n+\n+### Undo a merge commit\n+\n+A merge commit happens when 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 occured on zulip/upstream since you first started your work, it must perform a three-way merge and create a merge commit.","path":"docs/git-guide.md","position":750,"original_position":750,"commit_id":"a16725a1dac560b3a8cc116c82a8dc14f54cfe8d","original_commit_id":"a16725a1dac560b3a8cc116c82a8dc14f54cfe8d","user":{"login":"timabbott","id":2746074,"avatar_url":"https://avatars.githubusercontent.com/u/2746074?v=3","gravatar_id":"","url":"https://api.github.com/users/timabbott","html_url":"https://github.com/timabbott","followers_url":"https://api.github.com/users/timabbott/followers","following_url":"https://api.github.com/users/timabbott/following{/other_user}","gists_url":"https://api.github.com/users/timabbott/gists{/gist_id}","starred_url":"https://api.github.com/users/timabbott/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/timabbott/subscriptions","organizations_url":"https://api.github.com/users/timabbott/orgs","repos_url":"https://api.github.com/users/timabbott/repos","events_url":"https://api.github.com/users/timabbott/events{/privacy}","received_events_url":"https://api.github.com/users/timabbott/received_events","type":"User","site_admin":false},"body":"(maybe also mention that some graphical editors like the GitHub UI like to create these for you)","created_at":"2016-10-12T07:03:23Z","updated_at":"2016-10-12T07:09:54Z","html_url":"https://github.com/zulip/zulip/pull/1879#discussion_r82946422","pull_request_url":"https://api.github.com/repos/zulip/zulip/pulls/1879","_links":{"self":{"href":"https://api.github.com/repos/zulip/zulip/pulls/comments/82946422"},"html":{"href":"https://github.com/zulip/zulip/pull/1879#discussion_r82946422"},"pull_request":{"href":"https://api.github.com/repos/zulip/zulip/pulls/1879"}}},"pull_request":{"url":"https://api.github.com/repos/zulip/zulip/pulls/1879","id":87369914,"html_url":"https://github.com/zulip/zulip/pull/1879","diff_url":"https://github.com/zulip/zulip/pull/1879.diff","patch_url":"https://github.com/zulip/zulip/pull/1879.patch","issue_url":"https://api.github.com/repos/zulip/zulip/issues/1879","number":1879,"state":"open","locked":false,"title":"[WIP] docs: Add git workflow guide","user":{"login":"christi3k","id":104006,"avatar_url":"https://avatars.githubusercontent.com/u/104006?v=3","gravatar_id":"","url":"https://api.github.com/users/christi3k","html_url":"https://github.com/christi3k","followers_url":"https://api.github.com/users/christi3k/followers","following_url":"https://api.github.com/users/christi3k/following{/other_user}","gists_url":"https://api.github.com/users/christi3k/gists{/gist_id}","starred_url":"https://api.github.com/users/christi3k/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/christi3k/subscriptions","organizations_url":"https://api.github.com/users/christi3k/orgs","repos_url":"https://api.github.com/users/christi3k/repos","events_url":"https://api.github.com/users/christi3k/events{/privacy}","received_events_url":"https://api.github.com/users/christi3k/received_events","type":"User","site_admin":false},"body":"WIP on #1754. Not complete, but ready enough for some feedback.\r\n\r\nIn particular, I'd like feedback about:\r\n\r\n- Does the flow and organization of the doc make sense, especially for those less familiar with Git/GitHub?\r\n- Are there (more) specific scenarios I should cover in \"Reviewing changes\"? (I'm feeling a bit stuck on that section.\r\n- Likewise, are the specific scenarios that folks have encountered while working on Zulip I should cover in \"Getting out of trouble\"?\r\n\r\nKnown issue: Links to images aren't working. I'll file another issue about this.\r\n\r\n\r\n","created_at":"2016-09-29T18:42:07Z","updated_at":"2016-10-12T07:09:54Z","closed_at":null,"merged_at":null,"merge_commit_sha":"ee1a04ca4dd283f1a0986eb26cb348c89763263d","assignee":null,"assignees":[],"milestone":null,"commits_url":"https://api.github.com/repos/zulip/zulip/pulls/1879/commits","review_comments_url":"https://api.github.com/repos/zulip/zulip/pulls/1879/comments","review_comment_url":"https://api.github.com/repos/zulip/zulip/pulls/comments{/number}","comments_url":"https://api.github.com/repos/zulip/zulip/issues/1879/comments","statuses_url":"https://api.github.com/repos/zulip/zulip/statuses/a16725a1dac560b3a8cc116c82a8dc14f54cfe8d","head":{"label":"christi3k:1754-docs-add-git-workflow","ref":"1754-docs-add-git-workflow","sha":"a16725a1dac560b3a8cc116c82a8dc14f54cfe8d","user":{"login":"christi3k","id":104006,"avatar_url":"https://avatars.githubusercontent.com/u/104006?v=3","gravatar_id":"","url":"https://api.github.com/users/christi3k","html_url":"https://github.com/christi3k","followers_url":"https://api.github.com/users/christi3k/followers","following_url":"https://api.github.com/users/christi3k/following{/other_user}","gists_url":"https://api.github.com/users/christi3k/gists{/gist_id}","starred_url":"https://api.github.com/users/christi3k/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/christi3k/subscriptions","organizations_url":"https://api.github.com/users/christi3k/orgs","repos_url":"https://api.github.com/users/christi3k/repos","events_url":"https://api.github.com/users/christi3k/events{/privacy}","received_events_url":"https://api.github.com/users/christi3k/received_events","type":"User","site_admin":false},"repo":{"id":57913565,"name":"zulip","full_name":"christi3k/zulip","owner":{"login":"christi3k","id":104006,"avatar_url":"https://avatars.githubusercontent.com/u/104006?v=3","gravatar_id":"","url":"https://api.github.com/users/christi3k","html_url":"https://github.com/christi3k","followers_url":"https://api.github.com/users/christi3k/followers","following_url":"https://api.github.com/users/christi3k/following{/other_user}","gists_url":"https://api.github.com/users/christi3k/gists{/gist_id}","starred_url":"https://api.github.com/users/christi3k/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/christi3k/subscriptions","organizations_url":"https://api.github.com/users/christi3k/orgs","repos_url":"https://api.github.com/users/christi3k/repos","events_url":"https://api.github.com/users/christi3k/events{/privacy}","received_events_url":"https://api.github.com/users/christi3k/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/christi3k/zulip","description":"Zulip server - powerful open source group chat","fork":true,"url":"https://api.github.com/repos/christi3k/zulip","forks_url":"https://api.github.com/repos/christi3k/zulip/forks","keys_url":"https://api.github.com/repos/christi3k/zulip/keys{/key_id}","collaborators_url":"https://api.github.com/repos/christi3k/zulip/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/christi3k/zulip/teams","hooks_url":"https://api.github.com/repos/christi3k/zulip/hooks","issue_events_url":"https://api.github.com/repos/christi3k/zulip/issues/events{/number}","events_url":"https://api.github.com/repos/christi3k/zulip/events","assignees_url":"https://api.github.com/repos/christi3k/zulip/assignees{/user}","branches_url":"https://api.github.com/repos/christi3k/zulip/branches{/branch}","tags_url":"https://api.github.com/repos/christi3k/zulip/tags","blobs_url":"https://api.github.com/repos/christi3k/zulip/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/christi3k/zulip/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/christi3k/zulip/git/refs{/sha}","trees_url":"https://api.github.com/repos/christi3k/zulip/git/trees{/sha}","statuses_url":"https://api.github.com/repos/christi3k/zulip/statuses/{sha}","languages_url":"https://api.github.com/repos/christi3k/zulip/languages","stargazers_url":"https://api.github.com/repos/christi3k/zulip/stargazers","contributors_url":"https://api.github.com/repos/christi3k/zulip/contributors","subscribers_url":"https://api.github.com/repos/christi3k/zulip/subscribers","subscription_url":"https://api.github.com/repos/christi3k/zulip/subscription","commits_url":"https://api.github.com/repos/christi3k/zulip/commits{/sha}","git_commits_url":"https://api.github.com/repos/christi3k/zulip/git/commits{/sha}","comments_url":"https://api.github.com/repos/christi3k/zulip/comments{/number}","issue_comment_url":"https://api.github.com/repos/christi3k/zulip/issues/comments{/number}","contents_url":"https://api.github.com/repos/christi3k/zulip/contents/{+path}","compare_url":"https://api.github.com/repos/christi3k/zulip/compare/{base}...{head}","merges_url":"https://api.github.com/repos/christi3k/zulip/merges","archive_url":"https://api.github.com/repos/christi3k/zulip/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/christi3k/zulip/downloads","issues_url":"https://api.github.com/repos/christi3k/zulip/issues{/number}","pulls_url":"https://api.github.com/repos/christi3k/zulip/pulls{/number}","milestones_url":"https://api.github.com/repos/christi3k/zulip/milestones{/number}","notifications_url":"https://api.github.com/repos/christi3k/zulip/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/christi3k/zulip/labels{/name}","releases_url":"https://api.github.com/repos/christi3k/zulip/releases{/id}","deployments_url":"https://api.github.com/repos/christi3k/zulip/deployments","created_at":"2016-05-02T19:00:08Z","updated_at":"2016-05-02T19:00:14Z","pushed_at":"2016-10-11T19:15:21Z","git_url":"git://github.com/christi3k/zulip.git","ssh_url":"git@github.com:christi3k/zulip.git","clone_url":"https://github.com/christi3k/zulip.git","svn_url":"https://github.com/christi3k/zulip","homepage":"","size":116854,"stargazers_count":0,"watchers_count":0,"language":"Python","has_issues":false,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"zulip:master","ref":"master","sha":"c2b4fd86e4cbab7a05d26b875bd835a3c0d21008","user":{"login":"zulip","id":4921959,"avatar_url":"https://avatars.githubusercontent.com/u/4921959?v=3","gravatar_id":"","url":"https://api.github.com/users/zulip","html_url":"https://github.com/zulip","followers_url":"https://api.github.com/users/zulip/followers","following_url":"https://api.github.com/users/zulip/following{/other_user}","gists_url":"https://api.github.com/users/zulip/gists{/gist_id}","starred_url":"https://api.github.com/users/zulip/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/zulip/subscriptions","organizations_url":"https://api.github.com/users/zulip/orgs","repos_url":"https://api.github.com/users/zulip/repos","events_url":"https://api.github.com/users/zulip/events{/privacy}","received_events_url":"https://api.github.com/users/zulip/received_events","type":"Organization","site_admin":false},"repo":{"id":43160685,"name":"zulip","full_name":"zulip/zulip","owner":{"login":"zulip","id":4921959,"avatar_url":"https://avatars.githubusercontent.com/u/4921959?v=3","gravatar_id":"","url":"https://api.github.com/users/zulip","html_url":"https://github.com/zulip","followers_url":"https://api.github.com/users/zulip/followers","following_url":"https://api.github.com/users/zulip/following{/other_user}","gists_url":"https://api.github.com/users/zulip/gists{/gist_id}","starred_url":"https://api.github.com/users/zulip/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/zulip/subscriptions","organizations_url":"https://api.github.com/users/zulip/orgs","repos_url":"https://api.github.com/users/zulip/repos","events_url":"https://api.github.com/users/zulip/events{/privacy}","received_events_url":"https://api.github.com/users/zulip/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/zulip/zulip","description":"Zulip server - powerful open source group chat","fork":false,"url":"https://api.github.com/repos/zulip/zulip","forks_url":"https://api.github.com/repos/zulip/zulip/forks","keys_url":"https://api.github.com/repos/zulip/zulip/keys{/key_id}","collaborators_url":"https://api.github.com/repos/zulip/zulip/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/zulip/zulip/teams","hooks_url":"https://api.github.com/repos/zulip/zulip/hooks","issue_events_url":"https://api.github.com/repos/zulip/zulip/issues/events{/number}","events_url":"https://api.github.com/repos/zulip/zulip/events","assignees_url":"https://api.github.com/repos/zulip/zulip/assignees{/user}","branches_url":"https://api.github.com/repos/zulip/zulip/branches{/branch}","tags_url":"https://api.github.com/repos/zulip/zulip/tags","blobs_url":"https://api.github.com/repos/zulip/zulip/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/zulip/zulip/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/zulip/zulip/git/refs{/sha}","trees_url":"https://api.github.com/repos/zulip/zulip/git/trees{/sha}","statuses_url":"https://api.github.com/repos/zulip/zulip/statuses/{sha}","languages_url":"https://api.github.com/repos/zulip/zulip/languages","stargazers_url":"https://api.github.com/repos/zulip/zulip/stargazers","contributors_url":"https://api.github.com/repos/zulip/zulip/contributors","subscribers_url":"https://api.github.com/repos/zulip/zulip/subscribers","subscription_url":"https://api.github.com/repos/zulip/zulip/subscription","commits_url":"https://api.github.com/repos/zulip/zulip/commits{/sha}","git_commits_url":"https://api.github.com/repos/zulip/zulip/git/commits{/sha}","comments_url":"https://api.github.com/repos/zulip/zulip/comments{/number}","issue_comment_url":"https://api.github.com/repos/zulip/zulip/issues/comments{/number}","contents_url":"https://api.github.com/repos/zulip/zulip/contents/{+path}","compare_url":"https://api.github.com/repos/zulip/zulip/compare/{base}...{head}","merges_url":"https://api.github.com/repos/zulip/zulip/merges","archive_url":"https://api.github.com/repos/zulip/zulip/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/zulip/zulip/downloads","issues_url":"https://api.github.com/repos/zulip/zulip/issues{/number}","pulls_url":"https://api.github.com/repos/zulip/zulip/pulls{/number}","milestones_url":"https://api.github.com/repos/zulip/zulip/milestones{/number}","notifications_url":"https://api.github.com/repos/zulip/zulip/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/zulip/zulip/labels{/name}","releases_url":"https://api.github.com/repos/zulip/zulip/releases{/id}","deployments_url":"https://api.github.com/repos/zulip/zulip/deployments","created_at":"2015-09-25T16:37:25Z","updated_at":"2016-10-11T15:34:01Z","pushed_at":"2016-10-12T05:50:43Z","git_url":"git://github.com/zulip/zulip.git","ssh_url":"git@github.com:zulip/zulip.git","clone_url":"https://github.com/zulip/zulip.git","svn_url":"https://github.com/zulip/zulip","homepage":"","size":125818,"stargazers_count":4157,"watchers_count":4157,"language":"Python","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":734,"mirror_url":null,"open_issues_count":545,"forks":734,"open_issues":545,"watchers":4157,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/zulip/zulip/pulls/1879"},"html":{"href":"https://github.com/zulip/zulip/pull/1879"},"issue":{"href":"https://api.github.com/repos/zulip/zulip/issues/1879"},"comments":{"href":"https://api.github.com/repos/zulip/zulip/issues/1879/comments"},"review_comments":{"href":"https://api.github.com/repos/zulip/zulip/pulls/1879/comments"},"review_comment":{"href":"https://api.github.com/repos/zulip/zulip/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/zulip/zulip/pulls/1879/commits"},"statuses":{"href":"https://api.github.com/repos/zulip/zulip/statuses/a16725a1dac560b3a8cc116c82a8dc14f54cfe8d"}}}}
{"actor":{"display_login":"timabbott"}}