Git

by Gisle Hannemyr

This chapter describes using the command line tool git for version control when when interacting with the Drupal.org repo. It also introduces the Drupal.org project pages, and how to interact with the issue queue and source code repository accessible via those pages.

Table of contents

Introduction

The Drupal community makes extensive use of git, a distributed version control system. It is used to manage source code and to share code with one another.

Understanding how to use git is essential if you want to use hot-fixes available on the Drupal.org site before they are released, if you want to contribute patches to Drupal projects, and if you want to maintain a project yourself.

To work with git at Drupal.org, you need to create a user account by registering at the site, and obtain git access. To familiarise yourself with the way Drupal.org uses git see the Drupal.org git FAQ.

The Drupal.org issue queue

Each extension hosted on Drupal.org, whether a module or theme, has its own project page. For an introduction to project pages, please see the section in this ebook introducing extensions. The project page for jQuery Update is reproduced below:

project01.png
Project page for jQuery Update.

In the right margin of project page, under the heading “All issues”, are links to the project's issue queue. The issue queue is simply a list of messages from maintainers and users related to that project.

The issue queue an essential tool in the Drupal community. It is what makes it possible for community members to cooperate without attending physical meetings, and without knowing each other personally.

If you need help with a specific project, whether a module or a theme, you should go to the issue queue where the maintainers and active users of the module or theme will be hanging out. This makes it more likely that your question will be seen by people who can help you. Additionally, you can use the issue queue to report bugs in the module or theme.

The issue queue is not a forum. The issue queue allows any project user to post an issue summary to a specific project version and categorise it (e.g., bug report, feature request) and suggest a priority. Subsequently, the project maintainer assigns tasks to colleagues, and tracks the status (e.g., active, fixed). In this way, all specific concerns related to a specific project can be tracked.

Note that the issue summary is a wiki-page. As work on the issue progresses the issue summary should be updated with the latest status information.

When commenting on an issue for a project on Drupal.org, the recommended practice for linking to the issue is to just list the issue number in square brackets like the example below:

<ul>
  <li>[#650306].</li>
</ul>

This will automatically expand to the full issue's full title, with a link back to the issue.

See alsoPlease also read the Drupal.org documentation: Use the issue queue and Using the issue queue.

Install git

First, check if git is already installed:

$ git
-bash: git: command not found

If the command is not found, you first need to install git.

To install git on RHEL, do:

$ sudo yum install git

To install git on Ubuntu/Debian Gnu/Linux, do:

$ sudo apt-get install git

See alsoIf you use some other platform, you'll find git installers and installation guidelines for most platforms on the website git-scm.com. If you're using a Gnu/Linux operating system with a package manager, you should be able to use that to install git.

Version control with git

A version control system keeps track of the history of a source code repository (main project directory) and lets the developer change the repository into another state. A distributed version control lets the developer work with a local copy of the a repository. With git, every local copy contains the full history and lets you do almost anything locally.

One of the main advantages of using a version control system is branching. You can work on a stable development branch named “1.0.x”. At the same time you, or someone else in the development team, can work on a specific bugfix on parallel in a separate branch named “bugfix”, and on a new feature in a third branch. Having the ability to branch means that your stable development branch is not disturbed by these parallel efforts until it is ready. Then the result can be merged back into the development branch.

branches

In the illustration above, the green squares are snapshots of the source code of a particular project at certain points in time, and the grey squares are branch pointers. The red square is a special pointer named “HEAD”. The horizontal dimension in the illustration is time, flowing from left to right. There has been three branches of the source code, but the bugfix branch is already merged back into the 7.1-1.x development branch, while the feature branch is moving ahead on its own.

tipDon't worry if you do not understand every detail in the illustration or the terminology at the present point. This is just a broad overview. A more detailed explanation will follow, and when you reach the end of this chapter, you should find this diagram much clearer.

With git, you're allowed to clone repositories, e.g. create a local copy that is an exact copy of some existing repository including the complete history of the source code. Owners of repositories can synchronise changes to linked local copies of repositories via push (transferring changes to a remote repository) or pull (getting changes from a remote repository).

Git is a command line tool and is best used from the command line in a Unix or Gnu/Linux environment. A git command is the first word following “git” on the command line. For instance, to use the git help command, you type:

$ git help

This results in a list of the most commonly used git commands.

tipThere is also a graphical git repository browser named gitk that is written in tcl/tk. It displays changes in a repository or a selected set of commits. This includes visualising the commit graph, showing information related to each commit, and the files in the trees of each revision.

The git commands that will be described in this chapter are:

help
Display help information about git.
config
Gets and sets repository or global options.
clone
Clone an existing repository into a new directory.
status
Shows the current status of the working directory.
init
Create an empty local git repository or reinitialise an existing one.
add
Add a working file to the staging area.
commit
Commit a snapshot of the current staging area to the repository. Committing creates a new revision which can be retrieved later, for example if you want to see or work with the source code of an older version.
branch
List, create or delete branches.
log
Shows commit logs.
checkout
Checkout a snapshot (usually a branch or path) to the working directory.
merge
Merge changes from named branch into current branch.
rebase
Forward-port local commits to the updated upstream head.
clean
Remove untracked files from the working directory.
tag
List, create, delete or verify a tag object.
remote
Manage the set of remote repositories (“remotes“) whose branches you track.
fetch
Download objects and refs from another repository.
pull
Fetch and merge.
push
Push local changes to a remote repository.
apply
Apply a patch to files.
format-patch
Create and format a patch for submission.

Getting help

Without any arguments or options, the git help command just prints a list of the most commonly used git commands on the standard output. However the help command accepts options and arguments. Try the following versions of the help command:

$ git help --all
$ git help status

In the first example, the --all option is used to produce a list of all git commands (not only the most commonly used). In the second example help information about another git command (status) is requested.

See alsoThis chapter only scrapes the surface of using git in the Drupal environment, but I hope it is enough information here to get you started. For a gentle introduction to key concepts, read Tom Preston-Werner's The Git Parable. For a much more comprehensive description of what you can do with git, see Git Magic by Ben Lynn or GitHowTo by Alexander Shvets. The closest thing to an official git manual is Scott Chacon's book Pro Git book. For more information, see the page on Drupal.org listing other git resources and the Drupal git documentation.

Setting up

The CLI command git config lets you configure git. There are three options that specify what configuration file to interact with:

  1. --system. File: /etc/gitconfig. Settings apply to all users and repositories.
  2. --global. File: .gitconfig in users home directory. Settings apply to current user.
  3. --local. File: .git/config in repository. Settings apply to current repository only.

You must identify yourself to each installation of git you use (home, office, laptop, etc).

Here is an example of the necessary commands to establish identity:

$ git config --global user.name "John Smith"
$ git config --global user.email johnsmith@example.org

You should of course use your own real name and email-address. If you have created an account at Drupal.org, the recommended version of these two commands can be found at My Dashboard » Profile » Git access.

You'll only have to do this once at each device.

You may also define global aliases for common commands by editing .gitconfig directly. This alias outputs the history of the brach on a compact format:

[alias]
  hist = log --pretty=format:\"%h %ad | %s%d [%an]\" --graph --date=short

After registering yourself as a git user at Drupal.org, upload your public ssh key. My Dashboard » Profile » SSH keys.

If you don't have a public ssh key, learn how to create it in Unix notes.

To check your current local configuration, use this command:

$ git config --list

Unless you have established a global configuration, it will not return anything if you're not inside a local git repository.

If you use it inside a local git repository, it will also list values pulled form the the repository configuration . This means that the output may be different if run from a inside a repository, compared from the output you get if it is run outside a repository.

tipIf you have different user names and different remotes, it is recommended to configure each repository with specifics.

Creating a project

There is two ways to create a local git project.:

  1. Clone an existing (usually remote) git repository.
  2. Make an existing local directory a git project.

Cloning a repository

If you want to get a copy of an existing git repository you do so with the command clone. Note that the clone command pulls down nearly all the data in the repository.

For instance, to clone a copy of the repository for the Gateway skeleton for Grav from GitHub, you use one of the following commands:

$ git clone git://github.com/getgrav/grav-skeleton-gateway-site.git
$ git clone --branch master git://github.com/getgrav/grav-skeleton-gateway-site.git

The first checks out the default branch, the second checks out a specific branch.

With a few exceptions, Drupal project repositories are, with a few exceptions (drush is one of them) not hosted on GitHub. Instead, they're hosted on git servers provided by the Drupal Association.

If you want to work with existing Drupal code, perhaps to make a temporary bug-fix to the core or contributed part of your Drupal site without having to wait for the bug fix to appear in the project on Drupal.org, you should start by cloning (downloading) the relevant branch of the Drupal project you're interested in from a remote Drupal project server.

tipA branch is (usually a a succession of) committed source code snapshots with its own history. The branch pointer points to the most recent of these. Also note that while master branches are commonly used in the git world, the Drupal community uses version branches (e.g. 7.x-1.x, 1.0.x) instead. This is because a Drupal repository contains branches for several major versions of Drupal, and “master” does not indicate what Drupal version the project is compatible to.

For example, if you are one of maintainers of the Notify project, you may clone its repository and have its head pointing at the 2.0.x branch, with the following command:

$ git clone --branch 2.0.x git@git.drupal.org/project/notify.git

If you are not one of the project's maintainers, use this one instead:

$ git clone --branch 2.0.x https://git.drupalcode.org/project/notify.git

You will find the right clone-comamnd to use under the project's Version control tab on Drupal.org.

The clone command creates a directory named notify, initialises a .git directory inside it, make a local copy of that repository. If the branch option is included on the command line, it does a checkout of a working copy of the latest version of that particular branch. If you go into the new notify directory, you'll see that all the project files are there, ready to be worked on.

Note that you can also check out a particular branch in a separate step after you've cloned the repository. The three commands below accomplish that.

$ git clone git@git.drupal.org/project/notify.git
$ cd notify
$ git checkout 2.0.x

The main tool you use to determine the status of your files is the status command. If you run this command directly after a cloning a 2.0.x branch, you will see this:

$ git status
# On branch 2.0.x
nothing to commit (working directory clean)

This tells you what branch you're on (here 2.0.x). It also tells you that you have a clean working directory. By “clean” git means that there are no files in the working directory that is not tracked, and there are no tracked files that has been modified but not committed.

If you want to clone the repository into a directory named something other than notify, you can specify that as the next command-line option like this:

$ git clone --branch 2.0.x git@git.drupal.org/project/notify.git mynotify

The clone command can also be used locally and recursively, but this will not be discussed in this ebook.

Initialising a local repository

If you're already working on a project, but want to start tracking it with git, you want to initialise a local git repository to work with.

You do this by using the following command in the directory where you keep the project's files:

$ git init

This creates a default branch named master and a new sub-directory named .git. This sets up a skeleton git repository. Nothing is tracked yet, but the framework for doing so is in place.

If you check the status at this point, you will be told that all the files in the working directory is “untracked”. Example:

$ git status
# On branch master
#
# No commits yet
#
# Untracked files:
#   (use "git add ..." to include in what will be committed)
#
    #	README.md
#	fancy.info
#	fancy.install
#	fancy.module
nothing added to commit but untracked files present (use "git add" to track)

The next thing to do it to is make sure the files are tracked by git by adding them to the staging area. You can accomplish that with a few git add commands that specify the files you want to track. E.g.:

$ git add README.txt
$ git add fancy.*

If we check the status after doing this, we see that the status of the files have changed:

$ git status
# On branch master
#
# Initial commit
#
# Changes to be committed:
#   (use "git rm --cached ..." to unstage)
#
#	new file:   README.txt
#	new file:   fancy.info
#	new file:   fancy.install
#	new file:   fancy.module
#

Committing to a local repository

At this point, you are able to use the commit command to commit a snapshot of the current state of the staging area to the repository. You need to supply a message. If you use the -m option to input the message on the command line, it should be a single line of text that identifies the snapshot. E.g.:

$ git commit -m "Initial version of the fancy project"

(If you do not use the -m option, git will launch a text editor and prompt you for the message to include.)

See alsoTo learn more about commit messages, you may want to read the Drupal.org guidelines for commit messages, Writing good commit messages, and 5 Useful Tips For A Better Commit Message. Note that while single line commit messages are discouraged in some of these documents, single line commit messages are welcome in the Drupal community.

If we review the status after making this commit, we're back to a state were we have a clean working directory:

$ git status
# On branch master
nothing to commit (working directory clean)

If this is a Drupal project you should change the branch name from “master” to something that indicate what main version of Drupal the project is compatible with. Use the legacy version branch (e.g. 7.x-1.x) or semantic version branch (e.g. 1.0.x):

$ git branch -m master 1.0.x
$ git status
# On branch 1.0.x
nothing to commit (working directory clean)

If you want to skip the step where you add files you're already tracking the staging area, there is a shortcut. The -a option to the git commit command makes git automatically stage every file that is already tracked before doing the commit. E.g.:

$ git commit -am "Second commit"

Making minor changes

Sometimes, you want to amend a commit. For instance, let us say that you make a mistake when typing in the commit message:

$ git commit -m "Removed cpnfusing URLs"

In that case, you can remove the error by committing again, using the --amend option to amend the previous commit:

$ git commit --amend -m "Removed confusing URLs"

If you also want to add a file you've changed after you've committed:

$ git commit --amend -am "Updated CHANGELOG.txt"

The --amend option makes a new snapshot of your staging area and use it, as well as the new message, to replace the last commit. If you've made no changes to the staging area since your last commit, then your snapshot will look exactly the same and all you'll change is your commit message. If you've made changes to your staging area between the initial commit and the amend (say you forgot to add a file and fixed that) then the amended commit also changes the snapshot to reflect the changes in your staging area.

You need to be careful because amending changes the SHA-1 of the commit. Don't amend your last commit if you've already pushed it.

Basic local workflow

We'll get around to distributed use of git eventually, but first, let us only consider how git appears in a local context. git knows about three local storage areas:

  1. The repository (sometimes referred to as the git directory) where committed files are kept.
  2. The staging area (sometimes referred to as the git index), where files ready to be committed are kept.
  3. The working directory (sometimes referred to as the working tree), where you keep modified files as long as you are working on them.

Corresponding to the three storage areas are three states that a file may be in: committed, staged, or working:

  1. Committed means that a current snapshot of the file is safely stored in the repository.
  2. Staged means that the file is a working file is marked to be committed, but not yet committed.
  3. Working means that the file is checked out of the repository, is in the working directory, and is worked upon (i.e. edited).

Whether you've cloned a remote repository or initialised your own local repository, you should now be set up to use git for version control. But before doing so, you need to understand branches.

A branch is a named pointer into the repository. A branch consists of a succession of commits with its own history. Also, to know what branch you're currently on, git keeps a special local pointer called HEAD.

The idea behind branches is to allow you to create a new branch from an existing one and change the code within this branch independently from other branches. This makes it simple to go back to a previous branch if the new branch did not work out. It also allows teams to work in parallel on independent branches.

To work on a particular branch, the developer performs a checkout. This makes the working directory contain the snapshot that was committed for that particular branch. After checking out a branch, the files in the branch may be edited. When done, the changed files are added to the staging area and committed, as illustrated with the diagram below:

git workflow

The basic git local workflow goes something like this:

  1. You checkout the branch you want to work with from the repository.
  2. You edit the checked out files in your working directory.
  3. When done, you stage the files, adding snapshots of them to your staging area.
  4. Finally, you do a commit, which takes the edited files as they are in the staging area and stores that snapshot permanently in the repository.

After storing the snapshot in the repository, the developer can move on to working on another branch, knowing that the committed branch can be checked out again any time.

Now, let us look try this out in practice, using the fancy project introduced as an example.

We pick up the project just after making the initial commit. To see the status, current branch, and a log of all events, use the following three commands:

$ git status
# On branch 1.0.x
nothing to commit (working directory clean)
$ git branch
* 7.0.x
$ git log
commit 3e96d03a97591dedc0603223aad3ed1c2392a56f
Author: Bob Smith 
Date:   Fri Oct 12 19:08:44 2012 +0200

    Initial version of the fancy project.

The branch command tells us that there is only one (local) branch, and that it is named 1.0.x. The asterisk (*) to the left of the branch name indicates that this is the current branch.

The log command lists each commit with its SHA-1 hash, the author's name and email, the date written, and the commit message. The SHA-1 hash can be used later to identify the commit.

The named marker for a branch (usually referred to as the “branch pointer” will always point to the latest commit for the branch. This means that the 1.0.x branch pointer will move ahead when we change the code in this branch and commit them.

To illustrate how the branch pointer moves, we're going to create a new branch named “initial”, and then list the local branches:

$ git branch initial
$ git branch
  initial
* 1.0.x

Note that the current branch is still 1.0.x (as indicated by the *next to the branch name), but now an additional branch named initial also exists. At the moment, both branch pointers point to the same snapshot.

Now, go ahead and make some changes to the files in the working area. When done, do another commit:

$ git commit -a -m "Second commit"

This second commit moves the current branch pointer (1.0.x) and HEAD forwards, so we now have a branch tree that looks like this:

branch pointers

There are now two branches, one named initial pointing to the initial commit, and another named 1.0.x that has moved on to the latest (second) commit. This is how the log now looks like.

$ git log
commit 391a7317504b970adca391e9a85bab1f59d713cb
Author: Bob Smith 
Date:   Fri Oct 12 19:40:04 2012 +0200

    Second commit.

commit 3e96d03a97591dedc0603223aad3ed1c2392a56f
Author: Bob Smith 
Date:   Fri Oct 12 19:08:44 2012 +0200

    Initial version of the fancy project.

Now, if we want to use initial as a starting point for another branch, we only have to check out the initial branch from the repository.

$ git checkout initial

This results in the following position for the branch pointers, where HEAD points to the current branch:

branch pointers

And just to make sure that the current branch is initial:

$ git branch
* initial
  1.0.x

Now, the initial snapshot will be your starting point when you edit files and add them to the staging area.

The checkout command accepts arguments that are not branch names. For instance, you can checkout snapshots not associated with a branch by referring to them with an abbreviated version of their SHA-1 hash. You need to supply enough of the SHA-1 hash to make it unique, and at least four characters. Also, by adding the -v option to the branch command, we get to see the first six digits of the SHA-1 hash and the commit message of the last commit on each branch. Example:

$ git checkout 391a
Previous HEAD position was 3e96d03... Initial version of the fancy project.
HEAD is now at 391a731... Second commit.
$ git branch -v
* (no branch) 391a731 Second commit.
  initial     3e96d03 Initial version of the fancy project.
  1.0.x       391a731 Second commit.

When you develop a project, and make new commits, the current branch pointer will advance and point to new snapshots identified by their SHA-1 hash. You can depend on the SHA-1 hash as a permanent and unique identifier of a particular snapshot.

noteIf you go through these steps, the SHA-1 hash created for your branches will be different from the hash used in the examples in this chapter. There is no meaning to the SHA-1 hash. It is only a persistent identifier of a specific snapshot.

If you want to preserve this snapshot as a branch, you can now go ahead and create it as a new named branch. The -b option to the checkout command both creates a new named branch, and also makes it the current branch.

$ git checkout -b second
$ git branch -v
  initial     3e96d03 Initial version of the fancy project.
  1.0.x       391a731 Second commit.
* second      391a731 Second commit.

The diagram below shows where the branch pointers are at this point:

branch pointers

Now, checkout the 1.0.x branch again, make some changes and commit it again with message “Beyond second”. This moves the 1.0.x branch forwards. However, since the second branch is not active, it remains pointing at the same snapshot.

Listing the branches now should produce something like this:

$ git branch -v 
  initial 3e96d03 Initial version of the fancy project.
* 1.0.x   20782e3 Beyond second.
  second  391a731 Second commit.

Let's say you want to try out some alternative idea, so you go back and check out the initial branch again, make some changes, create a new branch name alt, commit that, and finally checkout the 1.0.x branch again. Listing the branches gives something like this:

$ git branch -v 
  alt     b65c49a Alternative
  initial 3e96d03 Initial version of the fancy project.
* 1.0.x   20782e3 Beyond second
  second  391a731 Second commit.

And this is a picture of the branch tree at this point.

branch pointers

We now have two alternative branches. Both have the branch named initial as their starting point, so some files and text is probably shared between the two. But some of the material may also be different versions of the same thing.

Useful checkout commands

To get to the most recent commit of a specific branch, use the name if the branch, e.g.:

$ git checkout 1.0.x

To get back to your previous HEAD:

$ git checkout -

To see a log of your most recent checkouts:

$ git reflog

Merging branches

When developing a project along alternative branches, we may want to integrate changes from one branch into another. This is done with the command merge.

The command merge will merge the named branch with the current branch. To merge the alt branch into the 1.0.x branch do the following:

$ git checkout 1.0.x
$ git merge alt
Merge made by recursive.
 MANIFEST.txt | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 60 insertions(+), 0 deletions(-)

Given the branch tree we've been working on, this is how it looks like after this merge:

branch pointers

Sometimes, the merge process is not fully automatic, and git will report a merge conflict. In that case, git will suspend the merge to allow you to resolve the conflict before proceeding.

The standard way to integrate changes from one branch into another is done with the merge command as shown above. It performs a three-way merge between the two latest branch snapshots (20782… and b65c4…) and the most recent common ancestor of the two (3e96d…), creating a new snapshot, and a commit (f6f9a…).

However, there is a slightly different route to merging where you use the command rebase before doing the merge. If there are no conflicts, plain merge, and rebase followed by merge, produces the same result, but the latter makes the history look “cleaner”, pushing the alternate branch ahead of the 1.0.x and the fast-forwarding the 1.0.x pointer to it. This makes it appear as if all changes were committed linearly

To do this, first use this pair of commands makes it appear as if the alt branch pointer is ahead of the 1.0.x branch pointer in the branch tree:

$ git checkout alt
$ git rebase 1.0.x

The go back to the 1.0.x branch, and then merge the alt branch. This merge will fast-forward the 1.0.x branch to incorporate the changes in the alt branch.

$ git checkout 1.0.x
$ git merge alt

If there are conflicts, using rebase usually requires extra work to resolve those conflicts, and a standard merge may offer a better route.

Ignoring files and directories

Placing names of files and directories in a special file named .gitignore to make git not add them to the index. It has no effect on files that are already tracked.

To stop tracking a file you need to remove it from the index. Example, to ignore a NOTES.txt that is tracked:

$ git rm --cached NOTES.txt

If you want to remove a whole folder, you need to remove all files in it recursively:

$ git rm -r --cached badfolder

If you download a repo that is set up to track .gitignore it probably applies to another developers local repo. Best practice is not to track .gitignore. To get make git completely forget about it, first add it to the list of files to ignore in you local .gitignore-file. Then:

$ git rm --cached .gitignore
$ git add .
$ git commit -am "Do not track .gitignore"

Deleting a branch

Provided the branch has been merged, to delete a local branch named “second”, use the following command:

$ git branch -d second

If the branch has not been fully merged, this will result in an error message. If you don't care about the code in this branch, and just want to delete it, use:

$ git branch -D second

This turorial hasn't discussed remotes yet, but for future reference, to delete a remote branch, use the push command and prefix the name of the branch to delete with a colon (:).

$ git push origin :second

You'll not be allowed to delete a remote branch if it is the default branch, so make sure you change this before doing a delete.

Discarding changes

There may be day when you hack before having coffee. Don't!

But if you've done this, and you haven't committed your changes yet, you can get back the last committed version of any file. For instance, to rollback “myfile.php”, you can use the following command:

$ git checkout -- myfile.php

To revert your entire working directory and staging area to the last commit, use following two commands:

$ git checkout .
$ git clean -df

The first command reverts the tracked files in the staging area to the last commit by discarding all changes to tracked files. The second command deletes all files that are not tracked from the working directory.

If you want to undo the previous commit;

$ git reset --soft HEAD~1

The command reset will roll your current HEAD branch back to the specified revision. In the example above, the latest commit is discarded – effectively making the last commit undone.

The flag --soft makes sure that the changes in undone revisions are preserved. After running the command, the changes will exist as uncommitted local modifications in the working directory.

If it is not necessary to retain these changes, use the --hard flag.

$ git reset --hard HEAD~1

If you want to undo a bad commit you can revert it:

$ git revert 41767c3

Unlike reset, it preserves the bad revert, but adds a new HEAD where whatever it did was removed. I.e. it does the equivalent of reset, followed by subsequent recommits of subsequest commits.

Source sonic 002: git reset vs git revert.

Squashing commits

Let us say you've made a few tiny commits, and before you push your work, you want to make to merge them into a larger commit. For instance, let's say your repository looks like this.

$ git log --pretty="%ad %h %s" --date=short
2014-06-06 62e2757 Fixed yet another typo.
2014-06-06 0359fd5 Added missing word to one of the strings.
2014-06-06 5fbc028 Fixed a misspelling.
2014-06-06 20c1b45 Removed a duplicated word.
2014-06-04 1d7d1af Added tag for 7.x-1.0-alpha1 release.
2014-06-02 c7c02f7 Corrected a serious error in the database schema.
2014-05-30 d802ac2 Initial commit

The last four commits are just trivial typographical corrections made to different strings. It may be a good idea to squash these into a single commit. The simplest way to do this is to use the rebase command in its interactive mode. The command for this is:

$ git rebase -i HEAD~4

This should fire up your editor with the following contents.

pick 20c1b45 Removed a duplicated word.
pick 5fbc028 Fixed a misspelling.
pick 0359fd5 Added missing word to one of the strings.
pick 62e2757 Fixed yet another typo.

# Rebase c7c02f7..62e2757 onto c7c02f7
#
# Commands:
#  p, pick = use commit
#  e, edit = use commit, but stop for amending
#  s, squash = use commit, but meld into previous commit
#
# If you remove a line here THAT COMMIT WILL BE LOST.
# However, if you remove everything, the rebase will be aborted.

Edit the first four lines to look like this:

pick 20c1b45 Removed a duplicated word.
squash 5fbc028 Fixed a misspelling.
squash 0359fd5 Added missing word to one of the strings.
squash 62e2757 Fixed yet another typo.

Basically this tells git to combine all four commits into the the first commit on the list. Once this is done and the text buffer saved, the editor fires up again, showing you the commit messages to all the commits involved:

# This is a combination of 4 commits.
# The first commit's message is:
Removed a duplicated word.

# This is the 2nd commit message:

Fixed a misspelling.

# This is the 3rd commit message:

Added missing word to one of the strings.

# This is the 4th commit message:

Fixed yet another typo.

Since we're combining commits, git let you create and save new commit message for the combined commit. Edit the message as you see fit, delete or comment out the messages you no longer want. Then save the buffer and quit. Once that is done, and your commits have been successfully squashed, and you should see a message like this:

[detached HEAD 6ddba5d] Corrected several typos in various strings.
 4 files changed, 7 insertions(+), 7 deletions(-)
Successfully rebased and updated refs/heads/1.0.x.

If you run into conflicts during the rebase, they're usually quite easy to resolve. However, if you get lost, the command git rebase --abort will bring you back to your previous state.

noteOnly rewrite history with rebase if the commits haven't been pushed an external repository. If others have based work off of the commits that you've deleted, plenty of conflicts will occur. It is important that you do not rewrite the history if it has been shared with others.

Differences

We have already encountered the status command. This command will tell you the name of the files that have changed, but no details about these changes.

To see the changes in more detail, there is the git diff command. This command is used to see the differences between two different points in the tree. For example to see how two branches differ, or to see what has changed from one commit to another.

The examples below are just the most common uses of diff. The command is very versatile and let you use a lot of different arguments to specify what to compare.

The most basic version of the diff command shows the differences between the files that have changed in the working directory and the staging area for the next commit.

$ git diff

Please note that git diff alone doesn't show all changes made since your last commit. It shows only the changes that are still unstaged. This means that if you've staged all of your changes, git diff will give you no output.

To see the differences between the files that have changed in the working directory and the most recent commit (whether they're staged or not), you can use the following variant of the command:

$ git diff HEAD

This will show the difference between the current working directory and the HEAD of the current branch committed to the repository.

The following two commands are equivalent and will show the differences between the HEAD of the current branch and its parent:

$ git diff HEAD^ HEAD
$ git diff HEAD~1 HEAD

To see the differences between the any pair of commits you can specify a numeric offset relative to the current HEAD like this:

$ git diff HEAD~4 HEAD~2

To see a summary with the names of the files changed and the type of change, you can use the argument --name-status. This argument will suppress the actual diff output. Example:

$ git diff HEAD^ --name-status

To see the differences between a specific file in another branch and a file current working directory, use this syntax:

$ git diff bugfix:myfile.php myfile.php

This will show the differences in the file named “myfile.php” in the branch named “bugfix” and the same file in the current working directory.

To recursively compare two directories that is managed with git without comparing the contents of .git, use one of the following commands:

$ diff -rq --exclude=.git a/ b/
$ diff -rq -x .git a/ b/

Viewing the past

To view an old version of a file, without checking it out from the repository, use the show command followed by a revision specification followed by the path to the file-name. E.g.:

$ git show HEAD~4:tests/pagenotfound.test
$ git show dae86e:tests/pagenotfound.test

Note that the path must start from the root of the repository.

Tags

Like other version control systems, git has the ability to tag specific points in history as being important. In Drupal, this functionality is specifically used to mark release points for contributed projects (e.g.: 7.x-1.0), which indicates the first official release of the Drupal 7 version of the project.

Two types of tags exist: lightweight and annotated. Lightweight tags are meant for private or temporary object labels, while annotated tags are meant for public releases.

I.e.: Lightweight tags are just bookmarks. They help you locate and go back to a specific point in history. Annotated tags tells you who created them, and sometimes also why. In a large project, that my be important information.

To create a lightweight tag “1.0-alpha”:

$ git tag 1.0-alpha

To create an annotated tag, use the option -a. When you create an annotated tag, you must also create a message that describes the tag. Example:

$ git tag -a 7.x-1.0 -m "Release of my first version for Drupal7!"

Tags are listed alphabetically, not chronologically. To list all tags present in the current repository, type:

$ git tag
…
7.x-1.0
7.x-1.0-alpha1
7.x-1.1
7.x-1.10
7.x-1.11
7.x-1.12
7.x-2.0
…

To look up information about a tag, use the show command. Example:

$ git show 7.x-1.12
tag 7.x-1.12
Tagger: webchick 
Date:   Wed Feb 1 14:04:15 2012 -0800

Release 7.x-1.12

commit 4d4080b17681ae674e10c077b72d00f0b1544e0c
Author: webchick 

This is an annotated tag, because it starts with a line starting with Tagger: that identifies the person that created the tag. A lightweight tag starts with the line commit.

You may check out a tagged snapshot:

$ git checkout 1.0-alpha

As always when you do not check out a named branch, you're put in a state with a detached HEAD. This is fine for experimentation, but if you want to retain the commits you make in this state, you must also create a new branch.

To delete a tag, use the option -d:

$ git tag -d 1.0-alpha

Do not delete tags pushed to Drupal.org.

Interacting with remotes

When you clone a remote repository, git automatically associates with the short-name “origin” to indicate that this is the original repository where the branch resides.

If you don't start out by cloning a remote directory, but instead want to create a remote origin based on a local git repository, you use the git command “remote add origin”. Example:

$ git remote add origin git@git.drupal.org:sandbox/bob/123456.git

The above command will assocate the drupal.org sandbox “git.drupal.org:sandbox/bob/123456.git”, owned by “bob”, with “origin”.

If there is already a value associated with “origin”, and you want to replace with another, you use this instead:

$ git remote set-url origin git@git.drupal.org:sandbox/bob/123456.git

In addition to the default (origin) you can associate any other short-name with a remote repository with the remote add command. Example:

$ git remote add notify git@git.drupal.org/project/notify.git

The command remote alone lets you see which remote servers you have configured. Adding the -v option also shows the URL that is associated with the short-name:

Here is an example of output from this command after cloning the main branch of the notify project and explicitly associating the short-name zink with the same remote repository.

$ git remote -v
origin	git@git.drupal.org/project/notify.git (fetch)
origin	git@git.drupal.org/project/notify.git (push)
zink	git@git.drupal.org/project/notify.git (fetch)
zink	git@git.drupal.org/project/notify.git (push)

If you want to see more information about a particular remote, you can use the command remote show, and specify the short-name of the remote you are interested in. This example shows the result of running this command after we've cloned the repository for the Drupal notify project.

$ git remote show origin
* remote origin
  Fetch URL: git@git.drupal.org/project/notify.git
  Push  URL: git@git.drupal.org/project/notify.git
  HEAD branch: master
  Remote branches:
    3.0.x-1.x tracked
    4.0.x-1.x tracked
    4.1.x-1.x tracked
    4.2.x-1.x tracked
    4.3.x-1.x tracked
    4.4.x-1.x tracked
    4.5.x-1.x tracked
    4.6.x-1.x tracked
    4.7.x-1.x tracked
    5.x-1.x   tracked
    5.x-2.x   tracked
    6.x-1.x   tracked
    7.x-1.x   tracked
    drop      tracked
    master    tracked
  Local branch configured for 'git pull':
    master merges with remote master
  Local ref configured for 'git push':
    master pushes to master (up to date)

Without any options, the branch command will list branches that has been checked out locally. With the option -a, both local and remote tracking branches will be listed. The option -v produces a verbose format, where the first six digits of the SHA-1 hash and the commit message of the last commit on the branch is shown. Example:

$ git branch -a -v
* 7.x-1.x                  27d89bb Issue #1159632 initial port to D7
  remotes/origin/3.0.x-1.x 174d865 notify.module - fixed minor v3.00 bug.
  remotes/origin/4.0.x-1.x 0a7488c Stripping CVS keywords
  remotes/origin/4.1.x-1.x cb25868 Stripping CVS keywords
  remotes/origin/4.2.x-1.x fa0f8cd Stripping CVS keywords
  remotes/origin/4.3.x-1.x 2fc981d Stripping CVS keywords
  remotes/origin/4.4.x-1.x 2a3af64 Stripping CVS keywords
  remotes/origin/4.5.x-1.x 69d95ad Removing translation directories
  remotes/origin/4.6.x-1.x 48f72ce Removing translation directories
  remotes/origin/4.7.x-1.x 6d40564 Removing translation directories
  remotes/origin/5.x-1.x   3e44f63 Removing translation directories
  remotes/origin/5.x-2.x   f3a8465 Removing translation directories
  remotes/origin/6.x-1.x   3c5f64b Removing translation directories
  remotes/origin/7.x-1.x   27d89bb Issue #1159632 initial port to D7
  remotes/origin/HEAD      -> origin/master
  remotes/origin/drop      27a0d5c This commit was manufactured as part …
  remotes/origin/master    f5bdc14 Removing translation directories

Even if a particular branch is only listed as “remote”, it is also present in the local repository, and checking it out will make it appear in the local working directory.

$ git checkout 6.x-1.x
Branch 6.x-1.x set up to track remote branch 6.x-1.x from origin.
Switched to new branch '6.x-1.x'

Synchronising with a remote

Git does not automatically check the remote when reporting status. The following high level command will bring all your remote referenes up to date.

$ git remote update

You may also use the fetch command to do the same thing. For example, to fetch from the origin, you do:

$ git fetch origin

This operation does not change any of your own branches and is safe to do without changing your working directory. It just makes sure that named heads and tags present in the remote repository, and the associated objects, is present in the local repository.

Using the status command after a remote update or fetch will then tell you about any differences between your local and the remote repository:

$ git status -u no

If the status message tells you that you are behind the remote, and that the branch can be “fast forwarded”, this means that pulling down the necessary commits from a remote branch and merging those into the current local branch will not create any conflicts. In that case, all that is required to synchronise your local copy of the branch with the remote, is to pull. I.e.:

$ git pull origin

Which, btw., is equivalent to:

$ git fetch origin
$ git merge

At some point in the project, there will be a time when you want to make your changes available on a development snapshot on the Drupal project remote server. This is what the push command is for. Adding the -u option makes sure that the local branch track the remote branch. So to push the changes on the local 1.0.x branch to a development snapshot on origin, commit your changes and use the following command:

$ git push -u origin 1.0.x

To make development snapshots pushed to the repository on the Drupal project remote server downloadable from the project page, click on the link Administer releases near the bottom of project's project page on Drupal.org. Checking the box below “Show snapshot release” will automatically package the snapshot into a tarball after it has been uploaded, and then link to it under “Downloads” on the project page. Packaging of snapshots may take up to 10 minutes, so there may be a delay before a packaged snapshot appears on the project page.

releases01.png
Check box to show snapshot release on the project page.

The other settings on this page control of tagged releases are shown (or not) on the project page.

If a local branch you want to share does not already exist on the remote repository, just pushing it will not work. You need to specify the tag on the command line. Example:

$ git push 1.0.0-alpha1

This will create the release 1.0.0-alpha1 at the remote, and push to it.

noteDrupal.org enforce certain Release naming conventions. If a release is tagged with a tag that does not follow the convention, such as "1.0.0-alpha-1" (unwanted hyphen), you can push it, but it will not show up when you try to create a new tagged release. You may also want to read DSE: What does rc stand for? It provides some guidance about the use of these tags.

See also DO: Creating a Project Release.

To create a tagged full release, you first have to tag the current HEAD with the release name, then push it as follows:

$ git tag 1.0.0
$ git push origin tag 1.0.0

To make the new tagged release downloadable from the project page, click on the link Add new release near the bottom of project's project page on Drupal.org. This takes you to a page with a roll-down menu that lets you select the tagged release to add. [XXXX add screenshot]

Pushing is only allowed if nobody else has pushed updates to the branch upstream since you cloned from the origin. If the remote repository is updated with somebody else's work, you need to pull their work first and merge it with yours before you will be allowed to push.

There is also a command to delete a remote branch, as described above.

Multiple remote users

To have multiple remote users sharing the local account, set up host aliases in ~/.ssh/config with a distict private key IdentityFile for each remote identity.

Below is an example of the entries for two users named "bob" and "fred" on the same server having different remote accounts:

# bob Drupal.org account.
Host bobhost
  HostName git.drupal.org
  User git
  IdentityFile ~/.ssh/id_rsa

# fred Drupal.org account.
Host fredhost
  HostName git.drupal.org
  User git
  IdentityFile ~/.ssh/id_rsa_fred

Make sure the private keys given as IdentityFile exists.

A project maintained as "bob" can now be cloned with the following command:

$ git clone --branch 1.0.x git@bobhost:project/example.git

Collaboration

If the question is: “How do I collaborate and share code with other developers?”, the best answer is git.

However, there are two basic ways of using git to share code: pull requests (aka. merge requests) and pathches. GitHub uses pull requests. On Drupal.org, patches has traditionally been used, but in 200, a variation of pull requests, called merge requests was introduced. All these are described below.

GitHub pull requests

On GitHub.com, you create a pull request to propose and collaborate on changes to a repository. Unless you've already has write access to the repository, you first need to fork the project on GitHub, and then create a feature branch to hold your committed changes.

  1. Fork the project you want to contribute to to your own GitHub repo (see Clone or download for URL).
  2. Clone a working copy to your local repo and create a new branch (git checkout -b branch).
  3. Change, commit and push your version to your fork on GitHub.
  4. Create a pull request by going to the compare page and click Create pull request.

Note that changes are always proposed in a separate branch, to ensure that the main branch is kept clean and tidy.

See alsoThe GitHub pull request is a very nice collaboration tool. A request immediately spawns a discussion where all comments, code reviews and followup activity of the request are captured chronologically as they happen. To learn more about pull requests, see the following pages on GitHub.com: Collaborating, Creating a pull request, Using pull requests.

GitLab CI

The Drupal community is now recommending that contributors leverage on GitLab CI framework by Using GitLab to Contribute to Drupal.

Contributions submitted as merge requests make it easy to inspect requested changes in GitLab and to commit them directly to the repo (i.e. without testing them locally). Ideally, testing should be done using GitLab's CI framework. Take care if there are no (or inadequate) server side CI unit tests.

See DO: Issue forks & merge requests, Reviewing and merging merge requests.

Creating a merge request

An issue fork is a temporary repository for working on source code changes for an issue. It starts out as a copy of the main repository for the project, but it allows all community members to commit and push changes. There can only be one issue fork per issue.

To create a new merge request press "Create an issue fork".

To see what commands you can use click "Show commands".

Reviewing and merging a merge request

Merges requests appear below the issue summary. The link to a merge request will be something like "MR !X mergeable", where X is an integer. If a request is mergeable, a button with the label "Merge" when you click the link to the merge request (if it don't appear, make sure you're logged in to GitLab as someone who are allowed to write to the repo). When you click this button, the merge will be committed to the Drupal repo, making it ahead of your local repo. To synchronise, your local repo, use the following pair of commands:

$ git remote update
$ git pull

AFAIK, there are no instructions for how a non-maintainer can merge in a merge request into their local copy of the repostitory. I've asked for expanded instructions in this forum post. The reply links to instructions about how to review a merge request in GitLab UI which is not relevant to my use case.

tipHowever, this works: To create a file that can be use to patch the code base for testing locally, click "plain diff" adjecent to the MR, and save the resulting page as a patch-file.

Drupal.org patches

On Drupal.org, a patch posted to a project's issue queue used to be the standard method to propose and collaborate on changes to a repository. They are now being replaced by merge requests to leverage on GitLab's CI testing framework.

See alsoA patch is a structured file that consists of a list of differences between one set of files and another. For a general introduction to patches in a Drupal context, see the Drupal community page about patches. Note that the Drupal community have strict requirements for submitted patch files that are intended to be used for official Drupal projects. For a detailed description of how to create a patch for a Drupal project, see the advanced patch contributor guide.

Applying a patch

A common task for a Drupal site admin is to install hot-fixes on the site. For instance, the latest release of some module your site depends on is badly broken, and no new release has yet been made officially available. Sometimes, when this happens, some enterprising individual has made a patch that addresses the problem available. How do you apply that patch to your configuration?

With git, you first must identify what branch the patch apply to. This is usually stated up-front by the supplier of the patch. If not, ask.

Then, you start out with making a clone of the branch you want to work with. This creates a local copy of the branch on your local machine. For example, to make a local clone of the 1.0.x branch of the Drupal Notify project, you can use the following command:

$ git clone --branch 1.0.x http://git.drupalcode.org/project/notify.git

Now you can go ahead and download the patch. If the file containing the patch is named notify-wrong_type-1159632-22.patch. the following git command will apply it:

$ git apply -v notify-wrong_type-1159632-22.patch

The -v switch just makes the output verbose. Omitting it makes git, like most Unix and Gnu/Linux programs, silent if things go well.

Creating and posting a patch

First, if you plan to make a patch, make sure that you work on a local branch with a different name than the branch cloned from the origin. For instance, if you cloned branch 1.0.x, switch to a local branch named myfix before commiting any changes:

$ git checkout -b myfix

After switching to a new, local branch, you can start working on the code, making as many changes as is necessary to fix a bug or add a feature. When you're satisfied with the result, you may want to share it with the Drupal community. To do this, you need to create a patch and post it in the appropriate issue queue on Drupal.org.

tipPatches are identified by issue number. Patch file names also contains a comment number. The issue number is simply the node ID for the node on Drupal.org where the issue is described. For instance, given the following node: https://www.drupal.org/node/1159632, the node ID is 1159632. Therefore, the issue number is “1159632”. The comment number is the comment number the patch file will be attached to when you upload it. It is one more than the last posted comment in the issue thread.

First make sure that the commit message mentions the issue number the patch is supposed to fix, and your name. If you didn't do this when you made the commit, you can use the amend option to the commit command to fix this. Here is an example:

$ git commit --amend -m "Issue #1159632 by bob: Fixed crash due to wrong type"

If you're just a single commit ahead of the branch you forked from, the simplest way to create a patch is the following command:

$ git format-patch -1

The number option indicates the number of commits to create patches for, but if you specify more than one, you'll get a set of patches that must be applied in the correct sequence. The patch files will be named after the commit messages. You may need to change the names to match Drupal conventions.

The following naming convention for patch files has been adopted by the Drupal community:

[module_name]-[short-description]-[issue-number]-[comment-number].patch

If you want to create a patch for more than a single commit, something like the following command may be used:

$ git format-patch 1.0.x --stdout > notify-wrong_type-1159632-22.patch

It creates a single patch file that will the fast-forward the named branch (1.0.x in the example) to the head of the current branch. This means that anyone can clone the 1.0.x branch from the central repository, use git to apply your patch (as described in the previous section), and have a snapshot identical to yours.

Committing a patch

If you're the maintainer of a project hosted on Drupal.org, one of your duties is to commit patches written by others to the project's repository after the patch has been reviewed and tested by the community and found to be good.

If the patch you want to commit to Drupal's git repository is not your own code, but a patch created by somebody else, it is important that authorship is credited to that person (and not you). If you locate the patch in the issue queue at Drupal.org, expanding the field Credit & committing will suggest the git commit command to use:

dreditor01.png
The suggested commit message.

You can edit the Commit message field to make the message more appropriate before copying the git command.

Sandboxes and full projects

If you want to be part of the special part the Drupal developer community that contributes code to the Drupal public code base, the first step towards learning the ropes is to set up a sandbox.

A sandbox project is a project that consists of experimental code. It may not yet be ready for public use, or it may just be an experiment never intended for public use. While sandbox projects reside on a public server that is very similar to the server hosting full projects, sandboxes comes without administrative hurdles and obligations of full projects. Anyone with git access on Drupal.org can set up a sandbox project and become that project's maintainer.

In addition to offering aspirant maintainers a place to learn how to maintain a public project, sandboxes is often used by experienced maintainers to get early versions of a project tested by a smaller part of the community before promoting the sandbox project to a full project.

If you've already created an account at Drupal.org and obtained git access, you're set up to create a sandbox project.

In your dashboard a Drupal.org, click on the tab Your Projects and then on the link Add new project. This takes you to a form that let you add a new sandbox project by filling in a formwhere you pick the project type and status, and provide a name and description for the project. In the examples in this section, I've used the name “My sandbox”.

createproject01.png

The remaining steps are outlined here.

After filling in the form and clicking Save, the Version control tab near the top of the new project page will tell you how to set up a local repository for the sandbox project and link the local and remote repositories. It will also tell you the URL of remote repository. Below is the nine steps you may use to create a local repository, put some minimal content in it, and associate it with the remote repository with the origin git@git.drupal.org:1234.git. When you do this, the origin will of course be different.

$ mkdir my_sandbox
$ cd my_sandbox
$ git init
$ echo "name = my_sandbox" > my_sandbox.info
$ git add my_sandbox.info
$ git commit -m "Initial commit"
$ git branch -m master 1.0.x
$ git remote add origin git@git.drupal.org:1234.git
$ git remote add origin gitusername@git.drupal.org:sandbox/gitusername/1234.git
$ git push origin 1.0.x

To set up a full project, replace 1234 with the project's shortname.

Here is, in plain English, a brief explanation of what these steps does:

  1. Create a local directory named my_sandbox.
  2. Make this the current directory.
  3. Initialise a local git repository in it.
  4. Create a skeleton info-file.
  5. Add this file to the staging area.
  6. Commit it locally
  7. Rename the branch from master to 1.0.x.
  8. Associate the short-name origin with your remote (sandbox) repository.
  9. Push the project, and make the remote branch.

Note that in order to be able push, you must authenticate yourself to the remote server. Without authentication, someone else would be able to poison your remote repository with malicious code. The preferred way of authentication is with ssh keys. However, if you've not set up an ssh key in your Drupal.org account, git will prompt you to authenticate using your Drupal.org password.

After a sandbox project has been created, a link to it will appear under the tab Your Projects in your dashboard when you're logged in on your account on Drupal.org. You should be able to clone branches from it, and push new content to it.

After the first push, the page accessible via the Version control tab on the remote server will change. Instead of telling the maintainer how to set up a local and remote repository, it will give you customised versions of some common git commands. The default is to show commands suitable for maintainers (i.e. those allowed to push). But checking the box labelled Non-maintainer? and clicking Show will display a version of the page better suited for a non-maintainer.

Becoming a git vetted contributor

https://www.drupal.org/node/1047190

[TBA]

Promoting a sandbox

When you've obtained git vetted access, you will have the option to promote the sandbox project to a full project.

createproject02.png

Demoting a project

It is also possible to demote a full project to a sandbox in order to archive it and repurpose its namespace.

In this example, the project named “Oldproject” is going to be demoted into a sandbox.

First, you need to create an empty sandbox. Sandboxes have numbers instead of characters in their short name. In this example, we will use “1234” for the short name, but you will need to use the actual number that is automatically assigned to your sandbox when you create it.

The screenshot below shows a typical sandbox that is beeing prepared to hold the archive of an obsolete project. You should set its Maitenance status to “Unsupported” and its Development status to “Obsolete”.

createproject03.png

After completing the form to create a sandbox project, you must press Save to have the sandbox created, you should get something like the screenshot below that confirms that the sandbox has been created.

createproject04.png

Press the Edit tab to learn the numeric short name of your project.

createproject05.png

You can no go ahead and clone the old project to your local system, followed by a git push of the complete repository to the newly created sandbox. Provided the short name of the old project is “oldproject”, your git user name is “gitusername”, and the short name of the newly created sandbox is “1234”, the following four commands in the Gnu/Linux CLI should do it:

$ git clone http://git.drupalcode.org/project/oldproject.git oldproject
$ cd oldproject
$ git remote set-url origin gitusername@git.drupalcode.org:sandbox/gitusername/1234.git
$ git push --all origin

It is now possible to delete “oldproject” on Drupal.org. Deleting a full project will free its namespace so that it may be repurposed. The --all argument to push ensures that commit history is preserved, and that all branches and tags of the old project is pushed.

Troubleshooting

If you are unable to push to a repo at Drupal.org and the error message tells you that you “cannot access” or are “unable to access” the repo, and this happens to be a project you have cloned previously without having to authenticate, the most likely case is that the remote origin url in your .git/config file is not using set up to use authentication.

This format uses authentication:

[remote "origin"]
        bob@git.drupalcode.org:project/jimsproject.git

This format does not use authentication:

[remote "origin"]
        https://git.drupal.org/project/jimsproject.git

The simplest fix is to clone the repo again, this time using authentication:

$ git clone --branch 1.0.x bob@git.drupal.org:project/jimsproject.git

Then change the new clone with your changes, commit, and push again.

Final word

In addition to downloading and applying patches, git will help you manage local source code and allow you do commit changes to the repository. But you commit to your local branch (not the one on the server). However, to get your changes back into the main branch, you do a git push. This transfers your committed changes up to the server.


Last update: 2019-07-23 [gh].