Difference between revisions of "Git"

From ArchWiki
Jump to: navigation, search
m (link from git prompt to the configuration part about coloring. reason: i thought i had to colorize bash to get the git colors because of the stated note.)
m (Repair link to "Git Tools - Revision Selection".)
 
(345 intermediate revisions by 46 users not shown)
Line 1: Line 1:
 
[[Category:Version Control System]]
 
[[Category:Version Control System]]
[[zh-CN:Git]]
+
[[es:Git]]
{{Article summary start}}
+
[[ja:Git]]
{{Article summary text|Installing and using the Git VCS}}
+
[[zh-hans:Git]]
{{Article summary heading|Related}}
+
{{Related articles start}}
{{Article summary wiki|Super Quick Git Guide}}: Generally about contributing to pacman, although it still serves as a practical Git tutorial
+
{{Related|Gitweb}}
{{Article summary wiki|Gitweb}}
+
{{Related|Cgit}}
{{Article summary wiki|Cgit}}
+
{{Related|HTTP tunneling#Tunneling Git}}
{{Article summary wiki|Subversion}}
+
{{Related|Subversion}}
{{Article summary wiki|Concurrent Versions System}}
+
{{Related|Concurrent Versions System}}
{{Article summary link|GitHub|https://github.com/}}
+
{{Related articles end}}
{{Article summary end}}
+
{{Quote|I've met people who thought that git is a front-end to GitHub. They were wrong, git is a front-end to the AUR.|[https://public-inbox.org/git/#didyoureallythinklinuswouldsaythat Linus T.]}}
  
[http://git-scm.com/ Git] is the version control system (VCS) coded by Linus Torvalds (the creator of the Linux kernel) after being criticized for using the proprietary BitKeeper with the Linux kernel. Git is now used to maintain sources for the Linux kernel as well as thousands of other projects, including [[Pacman]], Arch's package manager.
+
[[wikipedia:Git (software)|Git]] is the version control system (VCS) designed and developed by Linus Torvalds, the creator of the Linux kernel. Git is now used to maintain [[AUR]] packages, as well as many other projects, including sources for the Linux kernel.  
  
There is extensive documentation, including guides and tutorials, available from the [http://git-scm.com/documentation official web site].
+
== Installation ==
  
==Installation==
+
[[Install]] the {{Pkg|git}} package. For the development version, install the {{AUR|git-git}} package. Check the optional dependencies when using tools such as ''git svn'', ''git gui'' and ''gitk''.
{{Pkg|git}} can be installed with [[pacman]] from the [[Official Repositories|official repositories]]. If you care about using Git with other VCS software, mail servers, or using Git's GUI, pay close attention to the optional dependencies.
 
  
Bash completion (e.g. hitting {{keypress|Tab}} to complete commands you are typing) should work if you add this line to your {{ic|~/.bashrc}} file:
+
{{Note|To enable spell checking in ''git-gui'', {{Pkg|aspell}} is required, along with the dictionary corresponding to the {{ic|LC_MESSAGES}} [[environment variable]]. See {{Bug|28181}} and the [[aspell]] article.}}
{{bc|source /usr/share/git/completion/git-completion.bash}}
 
Alternatively, you can install the {{Pkg|bash-completion}} package to load the completions automatically for new shells.
 
  
If you want to use Git's built-in GUI (e.g. {{Ic|gitk}} or {{Ic|git gui}}) you should install the {{Pkg|tk}} package, or you will get a rather cryptic message:
+
== Configuration ==
{{bc|/usr/bin/gitk: line 3: exec: wish: not found.}}
+
 
 +
In order to use Git you need to set at least a name and email:
 +
 
 +
$ git config --global user.name  "''John Doe''"
 +
$ git config --global user.email "''johndoe@example.com''"
 +
 
 +
See [https://git-scm.com/book/en/Getting-Started-First-Time-Git-Setup Getting Started - First-Time Git Setup].
 +
 
 +
See [[#Tips and tricks]] for more settings.
 +
 
 +
== Usage ==
 +
 
 +
A Git repository is contained in a {{ic|.git}} directory, which holds the revision history and other metadata. The directory tracked by the repository, by default the parent directory, is called the working directory. Changes in the working tree need to be staged before they can be recorded (committed) to the repository. Git also lets you restore, previously committed, working tree files.
 +
 
 +
See [https://git-scm.com/book/en/Getting-Started-Git-Basics Getting Started - Git Basics].
 +
 
 +
=== Getting a Git repository ===
 +
 
 +
* Initialize a repository
 +
:{{ic|git init}}, see {{man|1|git-init}}
 +
* Clone an existing repository
 +
:{{ic|git clone ''repository''}}, see {{man|1|git-clone}}
 +
 
 +
=== Recording changes ===
 +
 
 +
Git projects have a staging area, which is an {{ic|index}} file in your Git directory, that stores the changes that will go into your next commit. To record a modified file you therefore firstly need to add it to the index (stage it). The {{ic|git commit}} command then stores the current index in a new commit.
 +
 
 +
==== Staging changes ====
 +
 
 +
* Add working tree changes to the index
 +
:{{ic|git add ''pathspec''}}, see {{man|1|git-add}}
 +
* Remove changes from the index
 +
:{{ic|git reset ''pathspec''}}, see {{man|1|git-reset}}
 +
* Show changes to be committed, unstaged changes and untracked files
 +
:{{ic|git status}}, see {{man|1|git-status}}
 +
 
 +
You can tell Git to ignore certain untracked files using {{ic|.gitignore}} files, see {{man|5|gitignore}}.
 +
 
 +
Git does not track file movement. Move detection during merges is based only on content similarity. The {{ic|git mv}} command is just there for convenience and is equivalent to:
 +
 
 +
$ mv -i foo bar
 +
$ git reset -- foo
 +
$ git add bar
 +
 
 +
==== Committing changes ====
 +
 
 +
The {{ic|git commit}} command records the staged changes to the repository, see {{man|1|git-commit}}.
 +
 
 +
* {{ic|-m}} – supply the commit message as an argument, instead of composing it in your default text editor
 +
* {{ic|-a}} – automatically stage files that have been modified or deleted (does not add untracked files)
 +
* {{ic|--amend}} – redo the last commit, amending the commit message or the committed files
 +
 
 +
{{Tip|Always commit small changes frequently and with meaningful messages.}}
 +
 
 +
==== Revision selection ====
 +
 
 +
Git offers multiple ways to specify revisions, see {{man|7|gitrevisions}} and [https://git-scm.com/book/en/v2/Git-Tools-Revision-Selection Revision Selection].
 +
 
 +
Many Git commands take revisions as arguments. A commit can be identified by any of the following:
 +
 
 +
* SHA-1 hash of the commit (the first 7 digits are usually sufficient to identify it uniquely)
 +
* Any commit label such as a branch or tag name
 +
* The label {{ic|HEAD}} always refers to the currently checked-out commit (usually the head of the branch, unless you used ''git checkout'' to jump back in history to an old commit)
 +
* Any of the above plus {{ic|~}} to refer to previous commits. For example, {{ic|HEAD~}} refers to one commit before {{ic|HEAD}} and {{ic|HEAD~5}} refers to five commits before {{ic|HEAD}}.
 +
 
 +
==== Viewing changes ====
 +
 
 +
Show differences between commits:
 +
 
 +
$ git diff HEAD HEAD~3
 +
 
 +
or between staging area and working tree:
 +
 
 +
$ git diff
 +
 
 +
View history of changes (where "''-N''" is the number of latest commits):
 +
 
 +
$ git log -p ''(-N)''
 +
 
 +
=== Undoing things ===
 +
 
 +
* {{ic|git reset}} - reset current HEAD to the specified state, see {{man|1|git-reset}}
 +
 
 +
* {{ic|git checkout}} - to restore working tree files, see {{man|1|git-checkout}}
 +
 
 +
=== Branching ===
 +
 
 +
Fixes and new features are usually tested in branches. When changes are satisfactory they can merged back into the default (master) branch.
 +
 
 +
Create a branch, whose name accurately reflects its purpose:
 +
 
 +
$ git branch ''help-section-addition''
 +
 
 +
List branches:
 +
 
 +
$ git branch
 +
 
 +
Switch branches:
 +
 
 +
$ git checkout ''branch''
 +
 
 +
Create and switch:
 +
 
 +
$ git checkout -b ''branch''
 +
 
 +
Merge a branch back to the master branch:
 +
 
 +
$ git checkout master
 +
$ git merge ''branch''
 +
 
 +
The changes will be merged if they do not conflict. Otherwise, Git will print an error message, and annotate files in the working tree to record the conflicts. The annotations can be displayed with {{ic|git diff}}. Conflicts are resolved by editing the files to remove the annotations, and committing the final version. See [[#Dealing with merges]] below.
 +
 
 +
When done with a branch, delete it with:
 +
 
 +
$ git branch -d ''branch''
 +
 
 +
=== Collaboration ===
 +
 
 +
A typical Git work-flow is:
 +
 
 +
# Create a new repository or clone a remote one.
 +
# Create a branch to make changes; then commit those changes.
 +
# Consolidate commits for better organization/understanding.
 +
# Merge commits back into the main branch.
 +
# (Optional) Push changes to a remote server.
 +
 
 +
==== Pull requests ====
 +
 
 +
After making and committing some changes, the contributor can ask the original author to merge them. This is called a ''pull request''.
 +
 
 +
To pull:
 +
 
 +
$ git pull ''location'' master
 +
 
 +
The ''pull'' command combines both ''fetching'' and ''merging''. If there are conflicts (e.g. the original author made changes in the same time span), then it will be necessary to manually fix them.
 +
 
 +
Alternatively, the original author can pick the changes wanting to be incorporated. Using the ''fetch'' option (and ''log'' option with a special {{ic|FETCH_HEAD}} symbol), the contents of the pull request can be viewed before deciding what to do:
 +
 
 +
$ git fetch ''location'' master
 +
$ git log -p HEAD..FETCH_HEAD
 +
$ git merge ''location'' master
 +
 
 +
==== Using remotes ====
 +
 
 +
Remotes are aliases for tracked remote repositories. A ''label'' is created defining a location. These labels are used to identify frequently accessed repositories.
 +
 
 +
Create a remote:
 +
 
 +
$ git remote add ''label'' ''location''
 +
 
 +
Fetch a remote:
 +
 
 +
$ git fetch ''label''
 +
 
 +
Show differences between master and a remote master:
 +
 
 +
$ git log -p master..''label''/master
 +
 
 +
View remotes for the current repository:
 +
 
 +
$ git remote -v
 +
 
 +
When defining a remote that is a parent of the fork (the project lead), it is defined as ''upstream''.
 +
 
 +
==== Push to a repository ====
 +
 
 +
After being given rights from the original authors, push changes with:
 +
 
 +
$ git push ''location'' ''branch''
 +
 
 +
When ''git clone'' is performed, it records the original location and gives it a remote name of {{ic|origin}}.
 +
 
 +
So what ''typically'' is done is this:
 +
 
 +
$ git push origin master
 +
 
 +
If the {{ic|-u}} ({{ic|--set-upstream-to}}) option is used, the location is recorded so the next time just a {{ic|git push}} is necessary.
 +
 
 +
==== Dealing with merges ====
 +
 
 +
See [http://git-scm.com/book/en/Git-Branching-Basic-Branching-and-Merging#Basic-Merge-Conflicts Basic Merge Conflicts] in the Git Book for a detailed explanation on how to resolve merge conflicts. Merges are generally reversible. If wanting to back out of a merge one can usually use the {{ic|--abort}} command (e.g. {{ic|git merge --abort}} or {{ic|git pull --abort}}).
 +
 
 +
=== History and versioning ===
 +
 
 +
==== Searching the history ====
 +
 
 +
{{ic|git log}} will give the history with a commit checksum, author, date, and the short message. The ''checksum'' is the "object name" of a commit object, typically a 40-character SHA-1 hash.
 +
 
 +
For history with a long message (where the "''checksum''" can be truncated, as long as it is unique):
 +
 
 +
$ git show (''checksum'')
 +
 
 +
Search for ''pattern'' in tracked files:
 +
 
 +
$ git grep ''pattern''
 +
 
 +
Search in {{ic|.c}} and {{ic|.h}} files:
 +
 
 +
$ git grep ''pattern'' -- '*.[ch]'
 +
 
 +
==== Tagging ====
 +
 
 +
Tag commits for versioning:
 +
 
 +
$ git tag 2.14 ''checksum''
 +
 
 +
''Tagging'' is generally done for [https://www.drupal.org/node/1066342 releasing/versioning] but it can be any string. Generally annotated tags are used, because they get added to the Git database.
 +
 
 +
Tag the current commit with:
 +
 
 +
$ git tag -a 2.14 -m "Version 2.14"
 +
 
 +
List tags:
 +
 
 +
$ git tag -l
 +
 
 +
Delete a tag:
 +
 
 +
$ git tag -d 2.08
 +
 
 +
Update remote tags:
 +
 
 +
$ git push --tags
 +
 
 +
==== Organizing commits ====
 +
 
 +
Before submitting a pull request it may be desirable to consolidate/organize the commits. This is done with the ''git rebase'' {{ic|--interactive}} option:
 +
 
 +
$ git rebase -i ''checksum''
 +
 
 +
This will open the editor with a summary of all the commits in the range specified; in this case including the newest ({{ic|HEAD}}) back to, but excluding, commit {{ic|''checksum''}}. Or to use a number notation, use for example {{ic|HEAD~3}}, which will rebase the last three commits:
 +
 
 +
pick d146cc7 Mountpoint test.
 +
pick 4f47712 Explain -o option in readme.
 +
pick 8a4d479 Rename documentation.
 +
 
 +
Editing the action in the first column will dictate how the rebase will be done. The options are:
 +
 
 +
* {{ic|pick}} — Apply this commit as is (the default).
 +
* {{ic|edit}} — Edit files and/or commit message.
 +
* {{ic|reword}} — Edit commit message.
 +
* {{ic|squash}} — Merge/fold into previous commit.
 +
* {{ic|fixup}} — Merge/fold into previous commit discarding its message.
 +
 
 +
The commits can be re-ordered or erased from the history (but be very careful with these). After editing the file, Git will perform the specified actions; if prompted to resolve merge problems, fix them and continue with {{ic|git rebase --continue}} or back out with the {{ic|git rebase --abort}} command.
 +
 
 +
{{Note|Squashing commits is only used for local commits, it will cause troubles on a repository that is shared by other people.}}
 +
 
 +
== Tips and tricks ==
 +
 
 +
=== Using git-config ===
 +
 
 +
Git reads its configuration from three INI-type configuration files:
 +
 
 +
* {{ic|/etc/gitconfig}} for system-wide defaults
 +
* {{ic|~/.gitconfig}} for user-specific configuration
 +
* {{ic|.git/config}} for repository-specific configuration
 +
 
 +
These files can be edited directly, but the usual method is to use ''git config'', as shown in the examples below.
 +
 
 +
List the currently set variables:
 +
 
 +
$ git config {--local,--global,--system} --list
 +
 
 +
Set the default editor from [[vim]] to [[nano]]:
  
== Configuration ==
 
Git reads its configuration from a few INI type configuration files.  In each git repository {{ic|.git/config}} is used for configuration options specific to that repository.  Per-user ("global") configuration in {{ic|$HOME/.gitconfig}} is used as a fall-back from the repository configuration.  You can edit the files directly but the preferred method is to use the git-config utility. For example,
 
 
  $ git config --global core.editor "nano -w"
 
  $ git config --global core.editor "nano -w"
adds {{Ic|<nowiki>editor = nano -w</nowiki>}} to the {{Ic|<nowiki>[core]</nowiki>}} section of your {{ic|~/.gitconfig}} file.
 
  
The [http://schacon.github.com/git/git-config.html man page for the git-config] utility has a fairly long list of variables which can be set.
+
Set the default push action:
 +
 
 +
$ git config --global push.default simple
 +
 
 +
Set a different tool for ''git difftool'' (''meld'' by default):
 +
 
 +
$ git config --global diff.tool vimdiff
 +
 
 +
See {{man|1|git-config}} and [http://git-scm.com/book/en/v2/Customizing-Git-Git-Configuration Git Configuration] for more information.
  
The two settings you should set before using Git are your name and email. These are used to sign commits you make.
+
=== Adopting a good etiquette ===
$ git config --global user.name "Firstname Lastname"
 
$ git config --global user.email "your_email@youremail.com"
 
  
===Colors in Git Prompt===
+
* When considering contributing to an existing project, read and understand its license, as it may excessively limit your ability to change the code. Some licenses can generate disputes over the ownership of the code.
{{ic|color.ui}} is also a very useful option to set - it colorizes all Git output.
+
* Think about the project's community and how well you can fit into it. To get a feeling of the direction of the project, read any documentation and even the [[#History and versioning|log]] of the repository.
$ git config --global color.ui true
+
* When requesting to pull a commit, or submit a patch, keep it small and well documented; this will help the maintainers understand your changes and decide whether to merge them or ask you to make some amendments.
 +
* If a contribution is rejected, do not get discouraged, it is their project after all. If it is important, discuss the reasoning for the contribution as clearly and as patiently as possible: with such an approach a resolution may eventually be possible.
  
==Basic Usage==
+
=== Speeding up authentication ===
  
===Cloning a repository===
+
You may wish to avoid the hassle of authenticating interactively at every push to the Git server.
  
git clone <repo location> <dir>
+
* If you are authenticating with SSH keys, use an [[SSH agent]]. See also [[SSH#Speeding up SSH]] and [[SSH#Keep alive]].
 +
* If you are authenticating with username and password, switch to [[SSH keys]] if the server supports SSH, otherwise try [https://git-scm.com/docs/git-credential-cache git-credential-cache] or [https://git-scm.com/docs/git-credential-store git-credential-store].
  
will clone a Git repository in a new directory inside your current directory. Leaving out {{ic|<dir>}}
+
=== Protocol Defaults ===
will cause it to name the folder after the Git repository. For example,
 
  
git clone git@github.com:torvalds/linux.git
+
If you are running a multiplexed SSH connection as shown above, Git over SSH might be faster than HTTPS. Also, some servers (like the AUR) only allow pushing via SSH. For example, the following config will set Git over SSH for any repository hosted on the AUR.
  
clones Github's mirror of the Linux kernel into a directory named "linux".
+
{{hc|~/.gitconfig|<nowiki>
 +
[url "ssh://aur@aur.archlinux.org/"]
 +
insteadOf &#61; https://aur.archlinux.org/
 +
insteadOf &#61; http://aur.archlinux.org/
 +
insteadOf &#61; git://aur.archlinux.org/
 +
</nowiki>}}
  
===Committing files===
+
=== Bash completion ===
  
Git's commit process involves two steps:
+
In order to enable Bash completion, source {{ic|/usr/share/git/completion/git-completion.bash}} in a [[Bash#Configuration_files|Bash startup file]]. Alternatively, install {{pkg|bash-completion}}.
  
# Add new files, add changes for existing files (both with {{ic|git add <files>}}), and/or remove files (with {{ic|git rm}}). These changes are put in a staging area called the index.
+
=== Git prompt ===
# Call {{ic|git commit}} to commit the changes.
 
  
Git commit will open up a text editor to provide a commit message.
+
The Git package comes with a prompt script. To enable it, source the {{ic|/usr/share/git/completion/git-prompt.sh}} script in a [[Autostarting#Shells|shell startup file]], then set a custom prompt with the {{ic|%s}} parameter:
You can set this editor to whatever you want by changing the {{ic|core.editor}} option with {{ic|git config}}.
 
  
Alternatively, you can use {{ic|git commit -m <message>}} to supply the commit message without opening the text editor.
+
* For [[Bash]]: {{ic|1=PS1='[\u@\h \W$(__git_ps1 " (%s)")]\$ '}}
 +
* For [[zsh]]: {{ic|1=setopt PROMPT_SUBST ; PS1='[%n@%m %c$(__git_ps1 " (%s)")]\$ '}}
  
Other useful commit tricks:
+
When changing to a directory of a Git repository, the prompt will change to show the branch name. Extra details can be set to be shown by the prompt:
  
{{ic|git commit -a}} lets you commit changes you have made to files already under Git control
+
{| class="wikitable"
without having to take the step of adding the changes to the index. You still have to add new files with git add.
+
|+
 +
! Shell variable !! Information
 +
|-
 +
| GIT_PS1_SHOWDIRTYSTATE    || '''+''' for staged, '''*''' if unstaged.
 +
|-
 +
| GIT_PS1_SHOWSTASHSTATE    || '''$''' if something is stashed.
 +
|-
 +
| GIT_PS1_SHOWUNTRACKEDFILES || '''%''' if there are untracked files.
 +
|-
 +
| GIT_PS1_SHOWUPSTREAM      || '''<,>,<>''' behind, ahead, or diverged from upstream.
 +
|}
  
{{ic|git add -p}} lets you commit specific parts of files you have changed.
+
{{ic|GIT_PS1_SHOWUPSTREAM}} will need to be set to {{ic|auto}} for changes to take effect.
This is useful if you have made a bunch of changes that you think would be best split into several commits.
 
  
===Pushing your changes===
+
{{Note|If you experience that {{ic|$(__git_ps1)}} returns {{ic|((unknown))}}, then there is a {{ic|.git}} folder in your current directory which does not contain any repository, and therefore Git does not recognize it. This can, for example, happen if you mistake Git's configuration file to be {{ic|~/.git/config}} instead of {{ic|~/.gitconfig}}.}}
  
To push your changes up to a server (such as Github), use
+
Alternatively, you can use one of git shell prompt customization packages from [[AUR]] such as {{AUR|bash-git-prompt}} or {{AUR|gittify}}.
  
git push <server name> <branch>
+
=== Visual representation ===
  
Adding {{ic|-u}} will make this server the default one to push to for this branch.
+
To get an idea of the amount of work done:
If you have cloned the repository as described above, the server will default to the location you cloned the
 
repository from (nicknamed "origin") and the branch will default to the master branch.
 
In other words, if you have followed this guide's instructions in cloning, {{ic|git push}} will suffice.
 
You can set up Git to push to multiple servers if you want, but that is a more advanced topic.
 
Branches will be discussed later in this guide.
 
  
===Pulling from the server===
+
$ git diff --stat
  
If you are working on multiple machines and want to update your local repository to what the server has, you use
+
''git log'' with forking representation:
  
  git pull <server name> <branch>
+
  $ git log --graph --oneline --decorate
  
Similarly to push, the server name and branch should have sane defaults, so {{ic|git pull}} should suffice.
+
''git log'' graph alias (i.e. ''git graph'' will show a decorated version):
Git pull is actually shorthand for doing two things:
 
  
# Calling {{ic|git fetch}}, which updates the local copy of what the server has. Such branches are called "remote" branches because they are mirroring remote servers.
+
$ git config --global alias.graph 'log --graph --oneline --decorate'
# Calling {{ic|git merge}}, which merges what the remote branch has with what you have. If your commit history is the same as the server's commit history, you will be automatically fast-forwarded to the latest commit on the server. If your history does not match (maybe someone else has pushed commits since you last synced), the two histories will be merged.
 
  
It is not a bad idea to get into the practice of using these two commands instead of {{ic|git pull}}. This way you can
+
=== Commit tips ===
check to make sure that the server contains what you would expect before merging.
 
  
===Examining history===
+
Reset to previous commit (very dangerous, erases everything to specified commit):
  
The command {{ic|git log}} shows the history of your current branch. Note that each commit is identified by a SHA-1 hash.
+
$ git reset --hard HEAD^
The author, commit date, and commit message follow. A more useful command is
 
  
git log --graph --oneline --decorate
+
If a repository address gets changed, its remote location will need to be updated:
  
which provides a display similar to TortoiseGit's log window. It shows the following:
+
$ git remote set-url origin git@''address'':''user''/''repo''.git
  
* The first 7 digits of each commit's SHA-1 hash (enough to be unique)
+
Signed-off-by line append (a name-email signature is added to the commit which is required by some projects):
* The {{ic|--graph}} option shows how any branches (if there are others) fork off from the current branch.
 
* The {{ic|--oneline}} option shows only the first line of each commit message
 
* The {{ic|--decorate}} option shows all commit labels (branches and tags)
 
  
It may be convenient to alias this command as {{ic|git graph}} by doing the following:
+
$ git commit -s
  
git config --global alias.graph 'log --graph --oneline --decorate'
+
Signed-off-by automatically append to patches (when using {{ic|git format-patch ''commit''}}):
  
Now typing {{ic|git graph}} will run {{ic|git log --graph --oneline --decorate}}.
+
$ git config --local format.signoff true
{{ic|git graph}} and {{ic|git log}} may be given the {{ic|--all}} flag in order to view all branches instead of just the current one.
 
Adding {{ic|--stat}} to one of these commands is also useful -
 
it shows which files each commit changed and how many lines were changed in each file.
 
  
===Dealing With Merges===
+
Commit specific parts of files that have changed. This is useful if there are a large number of changes made that would be best split into several commits:
  
Merges happen when you pull, as a result of a rebase operation, and when you merge one branch into another.
+
$ git add -p
Like other version control tools, when Git cannot automatically merge a commit, it turns to you.
 
See [http://git-scm.com/book/en/Git-Branching-Basic-Branching-and-Merging#Basic-Merge-Conflicts this section]
 
of the Git Book for an explanation on how to resolve merge conflicts.
 
If you screw up and would like to back out of the merge, you can usually abort the merge using the {{ic|--abort}} flag
 
with whatever command started the merge (e.g. {{ic|git merge --abort}}, {{ic|git pull --abort}}, {{ic|git rebase --abort}}).
 
  
==Taking Advantage of DVCS==
+
=== Signing commits ===
  
The above commands only provide the basics.
+
Git allows commits and tags to be signed using [[GnuPG]], see [https://git-scm.com/book/en/Git-Tools-Signing-Your-Work Signing Your Work].
The real power and convenience in Git (and other distributed version control systems) come from leveraging its local commits and fast branching.
 
A typical Git workflow looks like this:
 
  
# Create and check out a branch to add a feature.
+
{{Note|To use {{Pkg|pinentry}} curses for GPG signing make sure to {{ic|1=export GPG_TTY=$(tty)}} (alternatively use pinentry-tty) otherwise the signing step will fail if GPG is currently in a locked state (since it cannot prompt for pin).}}
# Make as many commits as you would like on that branch while developing that feature.
 
# Squash, rearrange, and edit your commits until you are satisfied with the commits enough to push them to the central server and make them public.
 
# Merge your branch back into the main branch.
 
# Delete your branch, if you desire.
 
# Push your changes to the central server.
 
  
===Creating a branch===
+
To configure Git to automatically sign commits:
  
  git branch <branch name>
+
  $ git config --global commit.gpgSign true
  
can be used to create a branch that will branch off the current commit.
+
=== Working with a non-master branch ===
After it has been created, you should switch to it using
 
  
git checkout <branch name>
+
Occasionally a maintainer will ask that work be done on a branch. These branches are often called {{ic|devel}} or {{ic|testing}}. Begin by cloning the repository.
  
A simpler method is to do both in one step with
+
To enter another branch beside master (''git clone'' only shows master branch but others still exist, {{ic|git branch -a}} to show):
  
  git checkout -b <branch name>
+
  $ git checkout -b ''branch'' origin/''branch''
  
To see a list of branches, and which branch is currently checked out, use
+
Now edit normally; however to keep the repository tree in sync be sure to use both:
  
  git branch
+
  $ git pull --all
 +
$ git push --all
  
===A word on commits===
+
=== Directly sending patches to a mailing list ===
  
Many of the following commands take commits as arguments. A commit can be identified by any of the following:
+
If you want to send patches directly to a mailing list, you have to install the following packages: {{Pkg|perl-authen-sasl}}, {{Pkg|perl-net-smtp-ssl}} and {{Pkg|perl-mime-tools}}.
  
* Its 40-digit SHA-1 hash (the first 7 digits are usually sufficient to identify it uniquely)
+
Make sure you have configured your username and e-mail address, see [[#Configuration]].
* Any commit label such as a branch or tag name
 
* The label {{ic|HEAD}} always refers to the currently checked-out commit (usually the head of the branch, unless you used {{ic|git checkout}} to jump back in history to an old commit)
 
* Any of the above plus {{ic|~}} to refer to previous commits. For example, {{ic|HEAD~}} refers to one commit before {{ic|HEAD}} and {{ic|HEAD~5}} refers to five commits before {{ic|HEAD}}.
 
  
===Commits as checkpoints===
+
Configure your e-mail settings:
  
In Subversion and other older, centralized version control systems, commits are permanent - once you make them,
+
$ git config --global sendemail.smtpserver ''smtp.example.com''
they are there on the server for everyone to see.
+
$ git config --global sendemail.smtpserverport ''587''
In Git, your commits are local and you can combine, rearrange, and edit them before pushing them to the server.
+
$ git config --global sendemail.smtpencryption ''tls''
This gives you more flexibility and lets you use commits as checkpoints. Commit early and commit often.
+
$ git config --global sendemail.smtpuser ''foobar@example.com''
  
===Editing the previous commit===
+
Now you should be able to send the patch to the mailing list (see also [http://www.openembedded.org/wiki/How_to_submit_a_patch_to_OpenEmbedded#Sending_patches OpenEmbedded:How to submit a patch to OpenEmbedded#Sending patches]):
  
  git commit --amend
+
  $ git add ''filename''
 +
$ git commit -s
 +
$ git send-email --to=''openembedded-core@lists.openembedded.org'' --confirm=always -M -1
  
allows you to modify the previous commit. The contents of the index will be applied to it,
+
== Git server ==
allowing you to add more files or changes you forgot to put in. You can also use it to edit the commit message,
 
if you would like.
 
  
===Squashing, rearranging, and changing history===
+
How to set up connecting to repositories using varying protocols.
  
git rebase -i <commit>
+
=== SSH ===
  
will bring up a list of all commits between {{ic|<commit>}} and the present, including {{ic|HEAD}} but excluding {{ic|<commit>}}.
+
To use the SSH protocol, first set up a public SSH key; for that follow the guide at [[SSH keys]]. To set up a SSH server, follow the [[SSH]] guide.
This command allows you rewrite history. To the left of each commit, a command is specified.
 
Your options are as follows:
 
  
* The "pick" command (the default) uses that commit in the rewritten history.
+
With SSH working and a key generated, paste the contents of {{ic|~/.ssh/id_rsa.pub}} to {{ic|~/.ssh/authorized_keys}} (be sure it is all on one line). Now the Git repository can be accessed with SSH by doing:
* The "reword" command lets you change a commit message without changing the commit's contents.
 
* The "edit" command will cause Git to pause during the history rewrite at this commit. You can then modify it with {{ic|git commit --amend}} or insert new commits.
 
* The "squash" command will cause a commit to be folded into the previous one. You will be prompted to enter a message for the combined commit.
 
* The "fixup" command works like squash, but discards the message of the commit being squashed instead of prompting for a new message.
 
* Commits can be erased from history by deleting them from the list of commits
 
* Commits can be re-ordered by re-ordering them in the list. When you are done modifying the list, Git will prompt you to resolve any resulting merge problems (after doing so, continue rebasing with {{ic|git rebase --continue}})
 
  
When you are done modifying the list, Git will perform the desired actions.
+
$ git clone ''user''@''foobar.com'':''my_repository''.git
If Git stops at a commit (due to merge conflicts caused by re-ordering the commits or due to the "edit" command),
 
use {{ic|git rebase --continue}} to resume. You can always back out of the rebase operation with {{ic|git rebase --abort}}.
 
  
{{warning|Only use {{ic|git rebase -i}} on local commits that have not yet been pushed to anybody else.
+
You should now get an SSH yes/no question, if you have the SSH client setting {{ic|StrictHostKeyChecking}} set to {{ic|ask}} (the default). Type {{ic|yes}} followed by {{ic|Enter}}. Then you should have your repository checked out. Because this is with SSH, you also have commit rights now.
Modifying commits that are on the central server will cause merge problems for obvious reasons.}}
 
  
{{note|Vim makes these rebase operations very simple since lines can be cut and pasted with few keystrokes.}}
+
To modify an existing repository to use SSH, the remote location will need to be redefined:
  
==Git Prompt==
+
$ git remote set-url origin git@localhost:''my_repository''.git
The Git package comes with a prompt script. To enable the prompt addition you will need to source the git-prompt.sh script and add {{Ic|$(__git_ps1 " (%s)")}} to your PS1 variable.
 
* Add the following line to your {{ic|~/.bashrc}}/{{ic|~/.zshrc}}:
 
source /usr/share/git/completion/git-prompt.sh
 
* For Bash:
 
PS1='[\u@\h \W$(__git_ps1 " (%s)")]\$ '
 
{{Note|For information about coloring your Bash prompt, see [[Color_Bash_Prompt]]}}
 
{{Note|For information about coloring your Git prompt, see [[#Colors in Git Prompt]]}}
 
  
* For zsh:
+
Connecting on a port other than 22 can be configured on a per-host basis in {{ic|/etc/ssh/ssh_config}} or {{ic|~/.ssh/config}}. To set up ports for a repository (here 443 as example):
PS1='[%n@%m %c$(__git_ps1 " (%s)")]\$ '
 
  
The {{Ic|%s}} is replaced by the current branch name. Git information is displayed only if you are navigating in a Git repository. You can enable extra information by setting and exporting certain variables to a non-empty value as shown in the following table:
+
{{hc|.git/config|2=
 +
[remote "origin"]
 +
    url = ssh://''user''@''foobar''.com:443/~''my_repository''/repo.git
 +
}}
  
{| border="1"
+
You are able to secure the SSH user account even more allowing only push and pull commands on this user account. This is done by replacing the default login shell by git-shell. Described in [https://git-scm.com/book/en/v2/Git-on-the-Server-Setting-Up-the-Server Setting Up the Server].
|+
 
! Variable !! Information
 
|-
 
| GIT_PS1_SHOWDIRTYSTATE || '''*''' for unstaged and '''+''' for staged changes
 
|-
 
| GIT_PS1_SHOWSTASHSTATE || '''$''' if something is stashed
 
|-
 
| GIT_PS1_SHOWUNTRACKEDFILES || '''%''' if there are untracked files
 
|}
 
  
In addition you can set the {{Ic|GIT_PS1_SHOWUPSTREAM}} variable to {{Ic|"auto"}} in order to see {{Ic|'''<'''}} if you are behind upstream, {{Ic|'''>'''}} if you are ahead and {{Ic|'''<>'''}} if you have diverged.
+
=== Smart HTTP ===
  
{{Note|If you experience that {{Ic|$(__git_ps1)}} returns {{Ic|((unknown))}}, then there's a {{Ic|.git}} folder in your current directory which doesn't contain any repository, and therefore Git does not recognize it. This can for example happen if you for some reason mistake Git's config-file to be {{Ic|~/.git/config}} instead of {{Ic|~/.gitconfig}}.}}
+
Git is able to use the HTTP(S) protocol as efficiently as the SSH or Git protocols, by utilizing the git-http-backend. Furthermore it is not only possible to clone or pull from repositories, but also to push into repositories over HTTP(S).
  
==Transfer Protocols==
+
The setup for this is rather simple as all you need to have installed is the Apache web server ({{pkg|apache}}, with {{ic|mod_cgi}}, {{ic|mod_alias}}, and {{ic|mod_env}} enabled) and of course, {{pkg|git}}.
===Smart HTTP===
 
Since version 1.6.6 git is able to use the HTTP(S) protocol as efficiently as SSH or Git by utilizing the git-http-backend. Furthermore it is not only possible to clone or pull from repositories, but also to push into repositories over HTTP(S).
 
  
The setup for this is rather simple as all you need to have installed is the Apache web server (with mod_cgi, mod_alias, and mod_env enabled) and of course, git:
+
Once you have your basic setup running, add the following to your Apache configuration file, which is usually located at:
# pacman -S apache git
 
  
Once you have your basic setup up and running, add the following to your Apache's config usually located at {{ic|/etc/httpd/conf/httpd.conf}}:
+
{{hc|/etc/httpd/conf/httpd.conf|
<Directory "/usr/lib/git-core*">
+
<Directory "/usr/lib/git-core*">
    Order allow,deny
+
    Require all granted
    Allow from all
+
</Directory>
</Directory>
 
 
   
 
   
SetEnv GIT_PROJECT_ROOT /srv/git
+
SetEnv GIT_PROJECT_ROOT /srv/git
SetEnv GIT_HTTP_EXPORT_ALL
+
SetEnv GIT_HTTP_EXPORT_ALL
ScriptAlias /git/ /usr/lib/git-core/git-http-backend/
+
ScriptAlias /git/ /usr/lib/git-core/git-http-backend/
 +
}}
  
The above example config assumes that your git repositories are located at {{ic|/srv/git}} and that you want to access them via something like <nowiki>http(s)://your_address.tld/git/your_repo.git</nowiki>. Feel free to customize this to your needs.
+
This assumes your Git repositories are located at {{ic|/srv/git}} and that you want to access them via something like: {{ic|<nowiki>http(s)://your_address.tld/git/your_repo.git</nowiki>}}.
  
{{Note|Of course you have to make sure that your Apache can read and write (if you want to enable push access) on your git repositories.}}
+
{{Note|Make sure that Apache can read and write to your repositories.}}
  
 
For more detailed documentation, visit the following links:
 
For more detailed documentation, visit the following links:
* http://progit.org/2010/03/04/smart-http.html
+
* https://git-scm.com/book/en/v2/Git-on-the-Server-Smart-HTTP
* https://www.kernel.org/pub/software/scm/git/docs/v1.7.10.1/git-http-backend.html
+
* https://git-scm.com/docs/git-http-backend
 +
 
 +
=== Git ===
  
===Git SSH===
+
{{Note|The Git protocol is not encrypted or authenticated, and only allows read access.}}
You first need to have a public SSH key. For that follow the guide at [[Using SSH Keys]]. To set up SSH itself, you need to follow the [[SSH]] guide. This assumes you have a public SSH key now and that your SSH is working.
 
Open your SSH key in your favorite editor (default public key name is {{ic|~/.ssh/id_rsa.pub}}), and copy its content ({{keypress|Ctrl+c}}).
 
Now go to your user where you have made your Git repository, since we now need to allow that SSH key to log in on that user to access the Git repository.
 
Open {{ic|~/.ssh/authorized_keys}} in your favorite editor, and paste the contents of id_rsa.pub in it. Be sure it is all on one line! That is important! It should look somewhat like this:
 
{{Warning|Do not copy the line below! It is an example! It will not work if you use that line!}}
 
<pre style='overflow:auto'>
 
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQCboOH6AotCh4OcwJgsB4AtXzDo9Gzhl+BAHuEvnDRHNSYIURqGN4CrP+b5Bx/iLrRFOBv58TcZz1jyJ2PaGwT74kvVOe9JCCdgw4nSMBV44cy+6cTJiv6f1tw8pHRS2H6nHC9SCSAWkMX4rpiSQ0wkhjug+GtBWOXDaotIzrFwLw== username@hostname
 
</pre>
 
Now you can checkout your Git repository this way (change where needed. Here it is using the git username and localhost):
 
git clone git@localhost:my_repository.git
 
You should now get an SSH yes/no question. Type {{ic|yes}} followed by {{keypress|Enter}}. Then you should have your repository checked out. Because this is with SSH, you also do have commit rights now. For that look at [[Git]] and [[Super Quick Git Guide]].
 
  
====Specifying a non-standard port====
+
[[start|Start and enable]] {{ic|git-daemon.socket}}.
Connecting on a port other than 22 can be configured on a per-host basis in {{ic|/etc/ssh/ssh_config}} or {{ic|~/.ssh/config}}. To set up ports for a repository, specify the path in {{ic|.git/config}} using the port number {{ic|N}} and the ''absolute path'' {{ic|/PATH/TO/REPO}}:
 
ssh://user@example.org:N/PATH/TO/REPO
 
Typically the repository resides in the home directory of the user which allows you to use tilde-expansion. Thus to connect on port N=443,
 
url = git@example.org:repo.git
 
becomes:
 
url = ssh://git@example.org:443/~git/repo.git
 
  
===Git daemon===
+
The daemon is started with the following options:
{{Note|The git daemon only allows read access. For write access see [[#Git SSH]].}}
 
This will allow URLs like "git clone git://localhost/my_repository.git".
 
  
Start git-daemon with root privileges.
+
ExecStart=-/usr/lib/git-core/git-daemon --inetd --export-all --base-path=/srv/git
# systemctl start git-daemon.socket
 
  
To run the git-daemon every time at boot, enable the service:
+
Repositories placed in {{ic|/srv/git/}} will be recognized by the daemon. Clients can connect with something similar to:
# systemctl enable git-daemon.socket
 
  
The daemon is started with the following parameters which are placed in the systemd service file.
+
  $ git clone git://''location''/''repository''.git
  ExecStart=-/usr/lib/git-core/git-daemon --inetd --export-all --base-path=/srv/git
 
  
So you have to place your repositories in /srv/git/ to be able to clone them with git daemon.
+
=== Setting access rights ===
  
Clients can now simply use:
+
To restrict read and/or write access, use standard Unix permissions. Refer to
git clone git://localhost/my_repository.git
+
[https://github.com/sitaramc/gitolite/blob/d74e58b5de8c78bddd29b009ba2d606f7fcb4f2d/doc/overkill.mkd when gitolite is overkill] for more information.
  
=== Git repositories rights ===
+
For fine-grained access management, refer to [[gitolite]] and [[gitosis]].
To restrict read/write access, you can simply use Unix rights, see http://sitaramc.github.com/gitolite/doc/overkill.html
 
  
For a fine-grained rights access, see [[gitolite]] and [[gitosis]]
+
== See also ==
  
==See also==
+
* Git man pages, see {{man|1|git}}
* [http://git-scm.com/book Pro Git book]
+
* [https://git-scm.com/book/en/ Pro Git book]
* [http://gitref.org/ Git Reference]
+
* [https://git.github.io/git-reference/ Git Reference] by GitHub
* https://www.kernel.org/pub/software/scm/git/docs/
+
* [http://nathanhoad.net/git-workflow-forks-remotes-and-pull-requests Git workflow: Forks, remotes, and pull requests]
* https://help.github.com/
+
* [https://wiki.videolan.org/Git VideoLAN wiki article]
 +
* [https://gist.github.com/grawity/4392747 A comparison of protocols GitHubGist]
 +
* [https://gun.io/blog/how-to-github-fork-branch-and-pull-request How to GitHub]

Latest revision as of 12:35, 10 April 2018

I've met people who thought that git is a front-end to GitHub. They were wrong, git is a front-end to the AUR.

Git is the version control system (VCS) designed and developed by Linus Torvalds, the creator of the Linux kernel. Git is now used to maintain AUR packages, as well as many other projects, including sources for the Linux kernel.

Installation

Install the git package. For the development version, install the git-gitAUR package. Check the optional dependencies when using tools such as git svn, git gui and gitk.

Note: To enable spell checking in git-gui, aspell is required, along with the dictionary corresponding to the LC_MESSAGES environment variable. See FS#28181 and the aspell article.

Configuration

In order to use Git you need to set at least a name and email:

$ git config --global user.name  "John Doe"
$ git config --global user.email "johndoe@example.com"

See Getting Started - First-Time Git Setup.

See #Tips and tricks for more settings.

Usage

A Git repository is contained in a .git directory, which holds the revision history and other metadata. The directory tracked by the repository, by default the parent directory, is called the working directory. Changes in the working tree need to be staged before they can be recorded (committed) to the repository. Git also lets you restore, previously committed, working tree files.

See Getting Started - Git Basics.

Getting a Git repository

  • Initialize a repository
git init, see git-init(1)
  • Clone an existing repository
git clone repository, see git-clone(1)

Recording changes

Git projects have a staging area, which is an index file in your Git directory, that stores the changes that will go into your next commit. To record a modified file you therefore firstly need to add it to the index (stage it). The git commit command then stores the current index in a new commit.

Staging changes

  • Add working tree changes to the index
git add pathspec, see git-add(1)
  • Remove changes from the index
git reset pathspec, see git-reset(1)
  • Show changes to be committed, unstaged changes and untracked files
git status, see git-status(1)

You can tell Git to ignore certain untracked files using .gitignore files, see gitignore(5).

Git does not track file movement. Move detection during merges is based only on content similarity. The git mv command is just there for convenience and is equivalent to:

$ mv -i foo bar
$ git reset -- foo
$ git add bar

Committing changes

The git commit command records the staged changes to the repository, see git-commit(1).

  • -m – supply the commit message as an argument, instead of composing it in your default text editor
  • -a – automatically stage files that have been modified or deleted (does not add untracked files)
  • --amend – redo the last commit, amending the commit message or the committed files
Tip: Always commit small changes frequently and with meaningful messages.

Revision selection

Git offers multiple ways to specify revisions, see gitrevisions(7) and Revision Selection.

Many Git commands take revisions as arguments. A commit can be identified by any of the following:

  • SHA-1 hash of the commit (the first 7 digits are usually sufficient to identify it uniquely)
  • Any commit label such as a branch or tag name
  • The label HEAD always refers to the currently checked-out commit (usually the head of the branch, unless you used git checkout to jump back in history to an old commit)
  • Any of the above plus ~ to refer to previous commits. For example, HEAD~ refers to one commit before HEAD and HEAD~5 refers to five commits before HEAD.

Viewing changes

Show differences between commits:

$ git diff HEAD HEAD~3

or between staging area and working tree:

$ git diff

View history of changes (where "-N" is the number of latest commits):

$ git log -p (-N)

Undoing things

  • git reset - reset current HEAD to the specified state, see git-reset(1)

Branching

Fixes and new features are usually tested in branches. When changes are satisfactory they can merged back into the default (master) branch.

Create a branch, whose name accurately reflects its purpose:

$ git branch help-section-addition

List branches:

$ git branch

Switch branches:

$ git checkout branch

Create and switch:

$ git checkout -b branch

Merge a branch back to the master branch:

$ git checkout master
$ git merge branch

The changes will be merged if they do not conflict. Otherwise, Git will print an error message, and annotate files in the working tree to record the conflicts. The annotations can be displayed with git diff. Conflicts are resolved by editing the files to remove the annotations, and committing the final version. See #Dealing with merges below.

When done with a branch, delete it with:

$ git branch -d branch

Collaboration

A typical Git work-flow is:

  1. Create a new repository or clone a remote one.
  2. Create a branch to make changes; then commit those changes.
  3. Consolidate commits for better organization/understanding.
  4. Merge commits back into the main branch.
  5. (Optional) Push changes to a remote server.

Pull requests

After making and committing some changes, the contributor can ask the original author to merge them. This is called a pull request.

To pull:

$ git pull location master

The pull command combines both fetching and merging. If there are conflicts (e.g. the original author made changes in the same time span), then it will be necessary to manually fix them.

Alternatively, the original author can pick the changes wanting to be incorporated. Using the fetch option (and log option with a special FETCH_HEAD symbol), the contents of the pull request can be viewed before deciding what to do:

$ git fetch location master
$ git log -p HEAD..FETCH_HEAD
$ git merge location master

Using remotes

Remotes are aliases for tracked remote repositories. A label is created defining a location. These labels are used to identify frequently accessed repositories.

Create a remote:

$ git remote add label location

Fetch a remote:

$ git fetch label

Show differences between master and a remote master:

$ git log -p master..label/master

View remotes for the current repository:

$ git remote -v

When defining a remote that is a parent of the fork (the project lead), it is defined as upstream.

Push to a repository

After being given rights from the original authors, push changes with:

$ git push location branch

When git clone is performed, it records the original location and gives it a remote name of origin.

So what typically is done is this:

$ git push origin master

If the -u (--set-upstream-to) option is used, the location is recorded so the next time just a git push is necessary.

Dealing with merges

See Basic Merge Conflicts in the Git Book for a detailed explanation on how to resolve merge conflicts. Merges are generally reversible. If wanting to back out of a merge one can usually use the --abort command (e.g. git merge --abort or git pull --abort).

History and versioning

Searching the history

git log will give the history with a commit checksum, author, date, and the short message. The checksum is the "object name" of a commit object, typically a 40-character SHA-1 hash.

For history with a long message (where the "checksum" can be truncated, as long as it is unique):

$ git show (checksum)

Search for pattern in tracked files:

$ git grep pattern

Search in .c and .h files:

$ git grep pattern -- '*.[ch]'

Tagging

Tag commits for versioning:

$ git tag 2.14 checksum

Tagging is generally done for releasing/versioning but it can be any string. Generally annotated tags are used, because they get added to the Git database.

Tag the current commit with:

$ git tag -a 2.14 -m "Version 2.14"

List tags:

$ git tag -l

Delete a tag:

$ git tag -d 2.08

Update remote tags:

$ git push --tags

Organizing commits

Before submitting a pull request it may be desirable to consolidate/organize the commits. This is done with the git rebase --interactive option:

$ git rebase -i checksum

This will open the editor with a summary of all the commits in the range specified; in this case including the newest (HEAD) back to, but excluding, commit checksum. Or to use a number notation, use for example HEAD~3, which will rebase the last three commits:

pick d146cc7 Mountpoint test.
pick 4f47712 Explain -o option in readme.
pick 8a4d479 Rename documentation.

Editing the action in the first column will dictate how the rebase will be done. The options are:

  • pick — Apply this commit as is (the default).
  • edit — Edit files and/or commit message.
  • reword — Edit commit message.
  • squash — Merge/fold into previous commit.
  • fixup — Merge/fold into previous commit discarding its message.

The commits can be re-ordered or erased from the history (but be very careful with these). After editing the file, Git will perform the specified actions; if prompted to resolve merge problems, fix them and continue with git rebase --continue or back out with the git rebase --abort command.

Note: Squashing commits is only used for local commits, it will cause troubles on a repository that is shared by other people.

Tips and tricks

Using git-config

Git reads its configuration from three INI-type configuration files:

  • /etc/gitconfig for system-wide defaults
  • ~/.gitconfig for user-specific configuration
  • .git/config for repository-specific configuration

These files can be edited directly, but the usual method is to use git config, as shown in the examples below.

List the currently set variables:

$ git config {--local,--global,--system} --list

Set the default editor from vim to nano:

$ git config --global core.editor "nano -w"

Set the default push action:

$ git config --global push.default simple

Set a different tool for git difftool (meld by default):

$ git config --global diff.tool vimdiff

See git-config(1) and Git Configuration for more information.

Adopting a good etiquette

  • When considering contributing to an existing project, read and understand its license, as it may excessively limit your ability to change the code. Some licenses can generate disputes over the ownership of the code.
  • Think about the project's community and how well you can fit into it. To get a feeling of the direction of the project, read any documentation and even the log of the repository.
  • When requesting to pull a commit, or submit a patch, keep it small and well documented; this will help the maintainers understand your changes and decide whether to merge them or ask you to make some amendments.
  • If a contribution is rejected, do not get discouraged, it is their project after all. If it is important, discuss the reasoning for the contribution as clearly and as patiently as possible: with such an approach a resolution may eventually be possible.

Speeding up authentication

You may wish to avoid the hassle of authenticating interactively at every push to the Git server.

Protocol Defaults

If you are running a multiplexed SSH connection as shown above, Git over SSH might be faster than HTTPS. Also, some servers (like the AUR) only allow pushing via SSH. For example, the following config will set Git over SSH for any repository hosted on the AUR.

~/.gitconfig
[url "ssh://aur@aur.archlinux.org/"]
	insteadOf = https://aur.archlinux.org/
	insteadOf = http://aur.archlinux.org/
	insteadOf = git://aur.archlinux.org/

Bash completion

In order to enable Bash completion, source /usr/share/git/completion/git-completion.bash in a Bash startup file. Alternatively, install bash-completion.

Git prompt

The Git package comes with a prompt script. To enable it, source the /usr/share/git/completion/git-prompt.sh script in a shell startup file, then set a custom prompt with the %s parameter:

  • For Bash: PS1='[\u@\h \W$(__git_ps1 " (%s)")]\$ '
  • For zsh: setopt PROMPT_SUBST ; PS1='[%n@%m %c$(__git_ps1 " (%s)")]\$ '

When changing to a directory of a Git repository, the prompt will change to show the branch name. Extra details can be set to be shown by the prompt:

Shell variable Information
GIT_PS1_SHOWDIRTYSTATE + for staged, * if unstaged.
GIT_PS1_SHOWSTASHSTATE $ if something is stashed.
GIT_PS1_SHOWUNTRACKEDFILES % if there are untracked files.
GIT_PS1_SHOWUPSTREAM <,>,<> behind, ahead, or diverged from upstream.

GIT_PS1_SHOWUPSTREAM will need to be set to auto for changes to take effect.

Note: If you experience that $(__git_ps1) returns ((unknown)), then there is a .git folder in your current directory which does not contain any repository, and therefore Git does not recognize it. This can, for example, happen if you mistake Git's configuration file to be ~/.git/config instead of ~/.gitconfig.

Alternatively, you can use one of git shell prompt customization packages from AUR such as bash-git-promptAUR or gittifyAUR.

Visual representation

To get an idea of the amount of work done:

$ git diff --stat

git log with forking representation:

$ git log --graph --oneline --decorate

git log graph alias (i.e. git graph will show a decorated version):

$ git config --global alias.graph 'log --graph --oneline --decorate'

Commit tips

Reset to previous commit (very dangerous, erases everything to specified commit):

$ git reset --hard HEAD^

If a repository address gets changed, its remote location will need to be updated:

$ git remote set-url origin git@address:user/repo.git

Signed-off-by line append (a name-email signature is added to the commit which is required by some projects):

$ git commit -s

Signed-off-by automatically append to patches (when using git format-patch commit):

$ git config --local format.signoff true

Commit specific parts of files that have changed. This is useful if there are a large number of changes made that would be best split into several commits:

$ git add -p

Signing commits

Git allows commits and tags to be signed using GnuPG, see Signing Your Work.

Note: To use pinentry curses for GPG signing make sure to export GPG_TTY=$(tty) (alternatively use pinentry-tty) otherwise the signing step will fail if GPG is currently in a locked state (since it cannot prompt for pin).

To configure Git to automatically sign commits:

$ git config --global commit.gpgSign true

Working with a non-master branch

Occasionally a maintainer will ask that work be done on a branch. These branches are often called devel or testing. Begin by cloning the repository.

To enter another branch beside master (git clone only shows master branch but others still exist, git branch -a to show):

$ git checkout -b branch origin/branch

Now edit normally; however to keep the repository tree in sync be sure to use both:

$ git pull --all
$ git push --all

Directly sending patches to a mailing list

If you want to send patches directly to a mailing list, you have to install the following packages: perl-authen-sasl, perl-net-smtp-ssl and perl-mime-tools.

Make sure you have configured your username and e-mail address, see #Configuration.

Configure your e-mail settings:

$ git config --global sendemail.smtpserver smtp.example.com
$ git config --global sendemail.smtpserverport 587
$ git config --global sendemail.smtpencryption tls
$ git config --global sendemail.smtpuser foobar@example.com

Now you should be able to send the patch to the mailing list (see also OpenEmbedded:How to submit a patch to OpenEmbedded#Sending patches):

$ git add filename
$ git commit -s
$ git send-email --to=openembedded-core@lists.openembedded.org --confirm=always -M -1

Git server

How to set up connecting to repositories using varying protocols.

SSH

To use the SSH protocol, first set up a public SSH key; for that follow the guide at SSH keys. To set up a SSH server, follow the SSH guide.

With SSH working and a key generated, paste the contents of ~/.ssh/id_rsa.pub to ~/.ssh/authorized_keys (be sure it is all on one line). Now the Git repository can be accessed with SSH by doing:

$ git clone user@foobar.com:my_repository.git

You should now get an SSH yes/no question, if you have the SSH client setting StrictHostKeyChecking set to ask (the default). Type yes followed by Enter. Then you should have your repository checked out. Because this is with SSH, you also have commit rights now.

To modify an existing repository to use SSH, the remote location will need to be redefined:

$ git remote set-url origin git@localhost:my_repository.git

Connecting on a port other than 22 can be configured on a per-host basis in /etc/ssh/ssh_config or ~/.ssh/config. To set up ports for a repository (here 443 as example):

.git/config
[remote "origin"]
    url = ssh://user@foobar.com:443/~my_repository/repo.git

You are able to secure the SSH user account even more allowing only push and pull commands on this user account. This is done by replacing the default login shell by git-shell. Described in Setting Up the Server.

Smart HTTP

Git is able to use the HTTP(S) protocol as efficiently as the SSH or Git protocols, by utilizing the git-http-backend. Furthermore it is not only possible to clone or pull from repositories, but also to push into repositories over HTTP(S).

The setup for this is rather simple as all you need to have installed is the Apache web server (apache, with mod_cgi, mod_alias, and mod_env enabled) and of course, git.

Once you have your basic setup running, add the following to your Apache configuration file, which is usually located at:

/etc/httpd/conf/httpd.conf
<Directory "/usr/lib/git-core*">
    Require all granted
</Directory>
 
SetEnv GIT_PROJECT_ROOT /srv/git
SetEnv GIT_HTTP_EXPORT_ALL
ScriptAlias /git/ /usr/lib/git-core/git-http-backend/

This assumes your Git repositories are located at /srv/git and that you want to access them via something like: http(s)://your_address.tld/git/your_repo.git.

Note: Make sure that Apache can read and write to your repositories.

For more detailed documentation, visit the following links:

Git

Note: The Git protocol is not encrypted or authenticated, and only allows read access.

Start and enable git-daemon.socket.

The daemon is started with the following options:

ExecStart=-/usr/lib/git-core/git-daemon --inetd --export-all --base-path=/srv/git

Repositories placed in /srv/git/ will be recognized by the daemon. Clients can connect with something similar to:

$ git clone git://location/repository.git

Setting access rights

To restrict read and/or write access, use standard Unix permissions. Refer to when gitolite is overkill for more information.

For fine-grained access management, refer to gitolite and gitosis.

See also