English version
Git 2.37.0 Usage RefCard
Written by Ludovic Dussart.
- Presentation
- Operating principles
- Cheat Sheet
- Start with a project
- Minimum configuration
- Ignore files (.gitignore)
- Typical development workflow with Git
- Branches and Conventions Workflow
- Commit conventions
- More Orders
- Enrich the Git configuration
- Tag creation
- Branch merge
- Branch rebase
- Add interactive
- Storage
- Conflict management
- Reflog (your safety net)
- Use a versioning platform
- Glossary
- References
- The Bear
Git is a version manager that records (historicizes) the evolution of changes made to a file or set of files over time.
Created in 2005 (on the initiative of Linus Torvalds, the creator of Linux), this new system offers the following promises:
- speed
- simple design
- support for non-linear developments (thousands of parallel branches)
- fully distributed
- ability to effectively manage large projects such as the Linux kernel (speed and compactness of data)
Since its birth in 2005, Git has evolved and matured to be easy to use while maintaining its initial qualities. The community quickly adopted it and today it is the reference tool for file versioning:
Credits : GitPrime
To use Git optimally, it is necessary to understand how it works to version your files.
Git manipulates objects that are identified and verified by a unique 40-character control string (SHA-1 fingerprint). Very important concept, this fingerprint is calculated according to the content of the file or the structure of the directory considered.
A SHA-1 fingerprint looks like this:
24b9da6552252987aa493b52f8696cd6d3b00373
Each object consists of 3 elements: a type, a size and a content.
- The blob
A blob is used to store file data. It is nothing more than a piece of binary data. It doesn't reference anything and has no attributes, not even a filename.
The
git showcommand allows to examine the contents of a blob
- The tree
A tree is like a directory — it references a list of other "trees" and/or other "blobs" (i.e. files and subdirectories). It allows to reconstruct the file hierarchy of a snapshot (commit).
The
git ls-treecommand allows to examine the contents of a tree (in a more detailed way than agit show)
- The commit (instantaneous)
A "commit" points to a single "tree" and marks it to represent the project at a certain point in time. It contains meta information about that point in time, such as a description, a timestamp, the author of the content since the last commit, a pointer to the last commit(s) , etc.
Note that a "commit" does not contain information about what has been modified; all changes are calculated by comparing the contents of the "tree" referenced in this "commit" with the "tree" associated with the parent(s) of the "commit".
The
git showorgit log --pretty=rawcommand allows you to examine your favorite “commits”
If we have a simple project with the following folder/file structure:
$>tree
.
|-- README
`--lib
|-- inc
| `-- tricks.rb
`-- mylib.rb
2 directories, 3 queuesIt will be handled by Git like this:
- The tag**
The tag allows you to put a label on a commit. Generally used to manage releases. This object is used to tag a source code version at a given time.
It contains an object name (simply named "object"), an object type, a tag name, the name of the person ("tagger") who created the tag, and a message (which may contain a signature , viewable using git cat-file)
Unlike other systems, Git does not manage and store the list of files and the changes made to each file over time. It captures a snapshot of your workspace content and saves a reference to that snapshot. To be efficient, if the files haven't changed, Git doesn't store the file again, just a reference to the original file it already checked in.
Unlike other systems, the logging of changes and the operations performed on your workspace are managed locally. Everything is stored on your disk and is your local repository. The publication of the changes on remote servers is done in a second step.
Generally, Git just adds data. When you perform actions in Git, almost all of them simply add data to the Git database. It is very difficult to make the system perform actions that are not reversible or to make it erase data in any way. However, as in most version control systems, you can lose or corrupt changes that have not yet been entered into the database; but once you've committed a snapshot to Git, it's very hard to lose it, especially if you additionally sync your local database with a remote repository.
This concept is essential
Git supports three states in which files can reside: modified, indexed, and committed
- Modified: means that you have modified the file but that it has not yet been validated in the database
- Indexed: means that you have marked a modified file in its current version to be part of the next snapshot (commit) of the project
- Validated: means the data is stored securely in your local database
Working directory (WD), index area and Git directory.
Credits: Git-scm
- The working directory (named WD thereafter) is a single extraction of a version of the project. These files are extracted from the compressed database in the Git directory and placed on disk for use or modification.
- The index area is a simple file, usually located in the Git directory, that stores information about what will be part of the next snapshot (commit). It is also sometimes called the preparation area.
- The Git directory is where Git stores your project's metadata and object database. It's the most important part of Git, and it's what gets copied when you clone a repository from another source.
The standard use of Git takes place in 3 steps:
- you modify files in your working directory
- You index modified files, which adds snapshots of those files to the index area
- you commit, which has the effect of switching snapshots of files from the index to the database in the Git directory
- Create a branch for any new development (cf. Workflow of branches and conventions)
- Prefix the name of your branch with a type (cf. Workflow of branches and conventions)
- A commit = a task (cf. Interactive addition)
- Prefer the indexing of lines (hunks) rather than files (cf. Add interactive)
- Use commit conventions (cf. Commit conventions)
- Rework your branch history before proposing it to be integrated (cf. Rebase interactive)
- Do not rewrite a history published on a collaborative remote branch
- I need to merge a
feature branchondevelop: cf. Branch merge - I need to label my application: cf. Tag creation
- I don't know where to start: cf. Typical development workflow with Git
- My branch is not up to date with the
developbranch: cf. Branch rebasing - I have just updated my branch and it has conflicts: cf. Conflict management
- I need to rewrite (clean up) the history of my branch: cf. Interactive rebase
- I made a bad manipulation and I lost my modifications: cf. Reflog
- I have finished working on my task and I must propose it to my team: cf. Submit a merge request
git config --global -lDisplays all global configurations. Use --local or --system to change the scope.
git config --global -eAllows you to edit global configurations. Use --local or --system to change the scope.
git config --global <parameter> <value>Allows you to define a global configuration. Use --local or --system to change the scope.
git-statusLists all changes that have not yet been committed.
git diff#WD vs index
git diff --staged # index vs HEAD (last commit)
git diff HEAD # WD & index vs HEAD (last commit)
git diff <sha1-commit1> <sha1-commit2> # commit1 vs commit2Displays the differences between two object references.
git-logDisplays the current branch's commit history. Use the options --oneline --graph for readability and --all to display the history of all branches.
git show <optional ref>Allows you to view the contents of an object.
git reflogShows the history of everything that happened on your local repository. Add the --relative-date option to add a notion of time.
git add --all
git add -A
git add .Adds all changes from all files to the index ready for commit.
git add <file>Adds all changes in the file to the index so they are ready for commit.
git add -p <optional file>Proposes the addition of changes, line by line of one or more files so that they are ready to be committed.
git reset <optional file>Moves changes of one or more files from index area to WD.
git restore <file>Cancel local modifications of a file.
git commit -m "<type>(<optional scope>): <commit message>"Creates a commit of previously indexed changes with a simple description. Chain the -m to also enter body and footer.
gitcommitProvides a prompt for creating a commit message, with previously indexed changes.
git commit --amendIncorporates previously indexed changes into the latest commit (HEAD). Add the --no-edit option to not edit the message.
git reset HEAD~<optional amount>Undo one or more commits. Their content (modifications to the files) is returned to the WD.
git branchLists all local branches. Add the --all option to show remote branches.
git branch <branch name>Creates a new branch (from the HEAD) with the given name. Change the name of a branch with the -m <old-name> <new-name> option.
git switch <branch name>Switch the HEAD to the designated branch and update the working directory. Use git switch - to switch to the previous reference.
git switch -c <branch name> <optional base-ref>Creates a new branch and positions itself on it. A second <base-ref> parameter initiates the branch from the targeted object.
git branch -d <branch name>Deletes the specified branch.
git tag <tagname>Create a tag on the HEAD commit.
git push <remote> <tagname>Publish the tag to the remote repository.
git reset --hard <SHA-1>Undoes all commits after the commit id but does not keep the changes.
git revert <SHA-1>Replays the reverse modifications of the targeted commit and creates a new "revert" commit.
git remote -vLists all configured remote repositories.
git remote show <remote>Show details about the remote repository.
git remote add <remote> <url>Adds a remote repository.
git fetch <remote> <branch>Updates the state of a remote repository in your local repository (but does not update the WD). Use the --all option to update all states of all remote repositories.
git merge <branch name>Merges (from above) the commits of the specified branch onto the current branch.
git rebase <branch name>Rewrites the commit history of the current branch by replaying, from below, that of the specified branch.
git pull <remote> <branch>Updates the status of a remote repository to your local repository and merges the changes into your workspace (WD).
git push -u <remote> <branch>Publish the commits of the specified branch to the remote repository (-u sets the upstream). Use <branch>:<new name> to publish the branch under a different name.
git init <project name>Creation of a new local repository (.git/) with the given name.
git clone <remote repository url>Clone a remote repository with all of its contents to your local repository. The -b option allows you to clone only the contents of a specific branch.
git config --global user.name "<your identity>"Sets the text that will be associated with commits for all projects. To configure it locally, remove the --global.
git config --global user.email "<your email address>"Sets the email address that will be associated with commits for all projects. To configure it locally, remove the --global.
git config --global alias.lg "log --color --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C( bold blue)<%an>%Creset' --abbrev-commit"Defines an lg alias providing a less verbose and more actionable view of the git log. You can add any other options after git lg.
Git provides a mechanism to ignore files in your workspace. Files to ignore are usually build artifacts (target on Maven, dist or build on NPM for example) and machine generated files that are either derived from your source repository or shouldn't be commits (/node_modules, /.idea, compiled code, etc).
Items specified in .gitignore will no longer appear in the output of git status, git add, etc. commands.
- Create a
.gitignorefile at the root of your project - Complete it with patterns of files to ignore based on development patterns. Here are some examples :
**/logs: the double*targets all directories everywhere in the local repository*.log: all files that end with.log!important.log: the!allows you to add exceptions to force the element to be taken into account and invalidate the general ruledebug.log: by default, patterns match files in any directory
- Index and commit your
.gitignorefile
A global
.gitignorecan be used thanks to thecore.excludesFileconfiguration:git config --global core.excludesFile ~/.gitignore
If you want to ignore a file that you have committed in the past, you will need to remove the file from your repository before adding a .gitignore rule for it. If you use the --cached option with git rm, the file will be removed from your repository, but will remain in your working directory as an ignored file.
echo debug.log >> .gitignore
git rm debug.log
git commit -m "chore(.gitignore): Start ignoring debug.log"This chapter aims to guide you step by step in your daily use with Git.
- To initiate or retrieve a project: Start with a project
- Git minimum configurations must be done: Git configurations
Use the branch workflows and naming conventions detailed in the chapter Branches and conventions workflow
-
Synchronize the initial branch with the remote repository version:
git pull origin <reference to starting snapshot>Example:
git pull origin develop -
Create your new branch from a snapshot (usually another branch):
git switch -c <your branch name> <reference to starting snapshot>Examples:
git switch -c <type>/<branch description> developgit switch -c <type>/<branch description> 38a1303git switch -c <type>/<branch description> 1.0.0
- Edit your files
- Add your changes to the index
- For all files (not recommended):
git add .orgit add --all - File by file (better):
git add <filename> - Line by line (hunk by hunk) (ideal):
git add -pfor all files,git add -p <filename>individually (see the chapter on interactive addition )
- For all files (not recommended):
- Check the status of your workspace (WD)
- To view changes tracked (indexed), or not:
git status - To compare the differences between your changes
- Between your workspace and the index:
git diff - Between index and
HEAD:git diff --staged - Between your workspace + index and the
HEAD:git diff HEAD
- Between your workspace and the index:
- To view changes tracked (indexed), or not:
- Undo adding changes if needed
- To undo additions to the index (revert your changes back to WD):
git reset
- To undo additions to the index (revert your changes back to WD):
- Create a snapshot (commit) containing your changes in the index:
git commit- Commit conventions must be enforced. Refer to the chapter Conventions de commits
- To create a single line commit message:
git commit -m "<type>(<optional scope>): <your message in 50 chars. max>" - To enter edit mode (and be able to enter a message header, body, and footer):
git commitThen use the format
<type>(<optional scope>): <description> <BLANK LINE> <optional body> <BLANK LINE> <optional footer> - To embed your changes in the previous commit (
HEAD):git commit --amend- and without modifying the message:
git commit --amend --no-edit
- and without modifying the message:
- To link your modifications to one of the previous commits (i.e. if these modifications concern an already created commit):
git commit --fixup=<SHA-1 of the target commit>
- Undo created snapshots if needed
- To modify the last snapshot and revert its modifications to the WD:
git reset HEAD~- To keep his changes in the index area:
git reset --soft HEAD~
- To keep his changes in the index area:
- To undo multiple commits:
git reset <SHA-1 which will become the last commit>git reset HEAD~<number of commits to undo>
- To modify the last snapshot and revert its modifications to the WD:
- View snapshot history or contents:
git lgorgit show <SHA-1 of commit> - Repeat the previous steps
At this point, everything you've done resides in your local repository (.git/ directory) and will remain there until you publish your changes.
- Add a remote repository if needed:
git remote add <remote> <url>- List your remote repositories with:
git remote -v
- List your remote repositories with:
- Update your workspace with the contents of the starting remote branch:
git pull origin <starting branch>- If modifications are still present in your WD:
git stash - Resolve conflicts if needed
- Apply your
stashif needed:git stash apply
- If modifications are still present in your WD:
- Review your history:
git lg - Clean up your history by reworking commits (merge commits linked by the same task together for example):
- Identify the number of commits specific to your branch (from the
HEADto the first commit of your branch) - Perform a commit rewrite on this number of commits:
git rebase -i --autosquash HEAD~<number of commits> - Refer to the chapter Rebase interactive to position the actions on your commits
- Walk through the
rebasesteps and resolve potential conflicts- Use
git rebase --continueafter each resolution - Use
git rebase --abortif you want to abort therebase
- Use
- Rerun your history:
git lg- Make sure your branch's parent commit hasn't been rewritten (reference to the original branch should still appear)
- Identify the number of commits specific to your branch (from the
- Publish your branch to the remote repository
- If it hasn't been released yet or you haven't rewritten the history:
git push <remote> <branch name> - If you rewrote the history:
git push <remote> <branch name> --force-with-lease- Tell your teammates that your branch has been force pushed
- If it hasn't been released yet or you haven't rewritten the history:
- Create a request to integrate your changes on one of the branches of the remote repository
- or do the merge by yourself if your organization allows it
In order to effectively control the life cycle of your developments, it is necessary to impose rules and processes for the management of the branches of your project. The most common workflow is branch by feature:
- Each feature is developed in a dedicated branch rather than in the
masterbranch. Thanks to this encapsulation, several developers can easily work on the same functionality without modifying the main code base. This also means that themasterbranch will never contain buggy code: a big plus for continuous integration environments. - This operation will make it possible to propose the modifications present on a branch to the versioning platforms in an isolated manner. It is then extremely easy for your team to give feedback on the work carried out.
Starting from this basic principle, Vincent Driessen (nvie) popularized a workflow offering great flexibility to teams; named Gitflow:
GitFlow is ideal for projects with a planned release cycle
- Two main branches are identified and must be protected
master: houses the production code. This branch is deployabledevelop: houses the pre-production code. It often contains the code of the next features tested and validated
- branches named
hotfix/<branch>may be created when patching production (master), usually to fix a bug.- patch branch must be initiated from
master - it must be merged on
master - as well as on
developso that the fixes are incorporated into the next tagged version ofdevelop
- patch branch must be initiated from
- All other branches will be feature branches. Whether it's a new feature, a fix, improvements to the documentation, or refactoring work: these developments should be isolated in dedicated branches, prefixed with a type, delimited by a
-or a/:<type>/<branch name>- the types introduced by the commits conventions can be taken over (
feat,fix,refactor, etc) - each new development must start from a branch (usually
develop) - the developments on these branches will be integrated sooner or later (when tested and validated) to the
developbranch
- the types introduced by the commits conventions can be taken over (
There are other branch workflows. You are free to choose (or mix?) the one that best suits the size and maturity of your team:
With the growing adoption of the tool among OSS communities in particular, a need to standardize the description of commits quickly became apparent. Driven by the Angular teams in particular, a commit convention quickly gained unanimous support and is now described in the form of a specification.
This specification provides a simple set of rules for creating an explicit and readable commit history. This convention ties into SemVer, describing features, fixes, and significant changes to commit messages.
The commit message should be structured as follows:
<type>(<optional scope>): <subject>
<BLANK LINE>
<optional body>
<BLANK LINE>
<optional footer>
- kind :
- fix: fixes a bug in the code (this is correlated with PATCH in SemVer).
- hotfix: fixes a bug in the production code (this correlates with PATCH in SemVer).
- feat: introduces a new feature in the code (this correlates with MINOR).
- chore / docs / style / perf / test / …: at the discretion of the teams
- scope: section of the code impacted by the modification
- subject: short description of less than 50 characters on the modifications made to the code
- body: long description (paragraphs) entering the details of the code modification.
- Must start with an empty line
- May contain
BREAKING CHANGEblock: introduces an API breaking change (this correlates with MAJOR in SemVer)
- footer: additional issue references regarding code changes (Fixes #13)
- Must start with an empty line
- May only contain
BREAKING CHANGE, external links, publication references and other meta information
- You can find sample commits at https://www.conventionalcommits.org
- You can automatically generate a CHANGELOG from your commits, based on these conventions: Conventional-changelog
Use
git+ TAB to have the terminal prompt you with the commandsUse TAB anytime to make Git autocomplete your command (commands, branch names, etc)
git help everydayA step-by-step guide to daily use of Git.
git clean -fDelete untracked files from WD. Use the -d option to delete directories as well.
git rm <file>... # git rm *.logChecks out and removes one or more files from WD and the Git index. Use --dry-run to test for the presence of the file. Use --cached to remove it only in the index area.
git mv <source> <destination>Moves a file or directory. The changes are added to the index but the commit is still required.
git add -N <optional file>Tells Git that changes to the file will be added later. Required to index new files (without their modifications) before the git add -p.
git sparse-checkout set <path>Allows you to recover only part of the files of a project. Practice on mono-repository projects.
git commit --fixup <commit>Create a fixup commit to be integrated into the <commit> commit during a rebase -i --autosquash.
git commit -pCreates a commit after an interactive add phase.
git cherry-pick <ref>Applies the object reference (commits, branch, etc) to the current branch by creating a new commit.
git revert <commit>Plays changes from the commit in the reverse direction and creates a new commit. Handy for reverting changes to a shared branch.
git rebase -i <commit>~ --autosquashAllows you to edit the commit history, from the <commit> commit to the HEAD. see Rebase interactive.
git rebase --onto <new branch> <old branch> <current branch>Allows you to change the home branch of the current branch. see Rebase --onto.
git shortlogShows commits grouped by author.
git difftoolStarts the comparison with the tool configured via diff.tool. Add the -t option to specify the tool to use (example: git difftool -t vscode).
git blame <file>Allows you to list the last modification date of a line and its author for a given file.
git grep <text>Similar to Unix grep: search for text in WD files. Many options are available.
git notes add <ref>
git notes append <ref>Allows you to add a note to an object.
git notes show <ref>Allows you to view an item's rating.
git push <remote> refs/notes/*Allows you to publish notes to a remote repository.
git remote rename <remote> <new name> # git remote rename origin ineatAllows you to rename a remote repository.
git remote set-url <remote> <url> # git remote set-url origin git@github.com:ineat/refcards.gitAllows you to redefine the url of a remote repository.
git clone -b <branch> --depth=<x> <url> <local dir>Clone only <x> commits from branch <branch> of remote repository <url> to a local directory <local dir>.
git show-refAllows you to list the references of the local repository.
- The
--systemoption allows you to set a configuration to an entire system.export LANG=<locale>allows to change the display language of Git messages (ex:export LANG=en_US.UTF-8)
git config --global core.editor <path/to/tool>: Allows to use an editor other thanviorvim- For Notepad++ (Windows) for example:
git config --global core.editor "'C:/Program Files (x86)/Notepad++/notepad++.exe' -multiInst -notabbar -nosession -noPlugin"git config --global core.pager '': Disablepagerfor all commands.git config --global core.autocrlf true: Automatically convert Windows line endings to Unix format (and vice versa).git config --global core.excludesFile <path/to/.gitignore>: Allows to define a global.gitignore.git config --global alias.<name> "<definition>": Allows you to define a reusable alias.
git config --global commit.template <path/to/template>: Set a default template for commit messages.
git config --global fetch.prune true: Thefetchcommand will be played with the--pruneoption automatically.
git config --global pull.rebase merges: Retain merge commits when they exist on the branch the changes came from.
git config --global merge.ff only: Only allow fast-forward merges (to guard against merge commits).git config --global merge.tool kdiff3: Configure thekdiff3tool for conflict resolution.git config --global diff.tool kdiff3: Configure thekdiff3tool for displaying diffs.
git config --global mergetool.keepBackup false: Delete.origfiles after conflict resolution.git config --global mergetool.keepTemporaries false: Remove temporary files after conflict resolution.
git config --global rebase.autosquash true: Positionfixupcommits automatically during arebase -i(option--autosquash).git config --global rebase.autoStash true:stashyour WD changes before apull, and apply thatstashright after.git config --global sequence.editor interactive-rebase-tool: use interactive-rebase-tool when doingrebase -i.
git config --global difftool.vscode.cmd 'code --wait --diff $LOCAL $REMOTE': Configures the command to run when usinggit difftool -t vscode.git config --global rerere.enabled true: Enablegit-rerere, i.e Git will remember some conflict resolutions and will automatically reapply in future resolutions for similar conflicts.git config --global pager.branch false: Allows viewing of all branches outside of edit mode. Thepagerattribute works for other commands liketag,log,diff, etc.git config --global help.autoCorrect immediate: If you mistype a command, Git will correct your input to play the inferred command automatically (test withgit statsfor example).
Git gives you the ability to tag your snapshots. Generally we use this feature to mark the publication states, ie the version numbers of releases (deliverables intended to be deployed on environments).
- Go to the branch where the snapshot you want to tag is located
- Invoke the command
git tag <tag number>- By default, the tag will carry the description of the annotated commit
- You can specify a message specific to your tag using the
-moption:git tag -a <tag number> -m <tag label>
- List the tags present on your local repository:
git tag - Publish your tag to the remote repository:
git push <remote> <tag number>
You can merge your branch in two different ways:
- via a so-called merge commit (explicit merge)
- or in fast-forward (implicit merge)
Consider the feat/A branch initiated from develop:
This is the default merge policy. It creates a new commit with the last commit of both branches as its parent:
A merge commit will be created by Git if
fast-forwardis not possible or if theno-ffoption is explicitly passed togit merge
- Use the merge commit only to highlight the addition of a new feature on your
develop - Use fast-forward in all other cases
The fast-forward allows to obtain a linear history after a merge. Fast-forward is possible if the first commit pointed to by the branch you merged is a direct descendant of the commit you were on before the merge.
- Use
git merge --ff-onlyorgit config --global merge.ff onlyto guard against a merge commit.- To make
fast-forwardpossible, use rebasing on the branch to be merged.
- To make
- Use
fast-forwardto keep your branch history linear, clean, and readable.
- Go to the branch that will receive the new changes:
git switch <receiving branch name> - Merge your branch on it, favoring
fast-forward:git merge <type>/<branch description> --ff-only- Resolve conflicts if needed
- Invoke
git merge --continueafter resolution
- Invoke
- If branches have been initiated since the branch update:
- Perform a rebase of the latter on the branches in question:
git rebase <your branch name>
- Perform a rebase of the latter on the branches in question:
- Resolve conflicts if needed
- Publish the new state of your branch to the remote repository:
git push- and branches that have been rebased if needed
- Delete the branch you just merged:
git branch -d <branch>- If also present on the remote repository:
git push --delete <remote> <branch>
- If also present on the remote repository:
Rebasing (rebase) allows to synchronize a branch (from below) with another. Very practical to benefit from the updates introduced since the initiation of your branch.
There are 3 kinds of branch rebasing:
- The standard mode: rebase (synchronize) a branch with respect to another
- The interactive mode: allows you to rewrite (rework) the history of the current branch
- onto mode: allows to attach the first commit of a branch to the
HEADof another branch
Consider that you are working on the feat/A branch:
A commit has just been added to the develop, which means that the feat/A branch is overdue.
It is therefore necessary here to update the feat/A branch compared to the develop branch using the git rebase command. This is an underneath update: ie the new develop commits will be played on the target branch. Existing commits (those in the feat/A branch) are overwritten since their parent commits change.
The git rebase can lead to conflicts if changes to common files collide. For more details on this part, see the chapter Conflict management.
In your versioning workflow, you will have to create more commits (fixup commit?) than tasks to perform. At the end of your developments, you must rework the history of your branch to:
- merge commits that relate to the same task
- rewrite the description of your commits if it is incomplete/wrong
- remove commits if needed
- in short, offer a clean and readable history to your team
This is why the interactive rebase is used. This is a classic rebase option: git rebase -i.
You need to tell rebase -i which parent commit you want to rewrite your history from:
-
using the SHA-1 of the parent commit:
git rebase -i <SHA-1-of-commit>. -
using a number of commits to rewrite from the
HEAD:git rebase -i HEAD~<number of commits to rewrite>.Examples:
git rebase -i 2edb99fif you want to rework all commits above the2edb99fcommitgit rebase -i HEAD~8if you want to touch up your last 8 commits
Git offers you a list of documented actions, of which the main ones are:
pick: leave the commit unchangedreword: allows to rewrite only the message of the commitedit: allows to integrate other modifications to the commit (equivalent togit commit --amend)squash: allows to merge 2 commits and to modify the message of the final commitfixup: allows you to merge the contents of the commit into the parent commit, without keeping the commit message.drop: allows you to delete a commit and the associated codereorder commits: you can reorder commits from top (oldest) to bottom (newest). Indispensable for thefixupor thesquashin particular, which apply to a parent commit
You have to position the commands instead of the pick depending on what you want to do. Git will then pop out all the commands and ask you to perform actions when necessary (entering a new message, resolving conflicts, etc.).
It is important to note that all commits affected by the rebase will be rewritten, even those left as is.
You can use git-interactive-rebase-tool to make your life easier during interactive rebases.
During the development phases, it regularly happens that branches are initiated from other branches under development, as shown in the following diagram:
Some of these branches of development can evolve independently of each other. Here is one of the most frequent cases:
- the
developbranch evolves. New commits are pushed (fixes, merged features, etc) - the team in charge of the
feat/Abranch decides to rebase its branch withdevelop(remember, thegit rebasegenerally rewrites the history)
This gives the following situation:
- finally, the
feat/Bbranch, initiated from theA2commit of thefeat/Abranch, must be merged beforefeat/Aand no longer needs the modifications introduced infeat/A`
The rebase --onto allows to attach the current branch to the HEAD of a new branch by determining the patches from the common ancestor of the branches: git rebase --onto <new branch> <old branch > <current branch>
You normally use the git add command to index your files before making a commit. One of the concepts of Git is to group together in a commit all the modifications related to a task. It often happens that a file contains changes that are not relevant to the current task.
It is then necessary to add only part of the lines of the file to the next commit.
The command git add -p allows to perform this action. Git will iterate over the modified files and will offer you to add, or not, the lines (hunks) of each of the files.
You have several choices here: (Stage this hunk [y,n,q,a,d,s,e,?]?)
It is difficult to know what these letters correspond to.
- Press the Enter key once (or type
?then Enter) to discover the details. y (yes): indexes the proposed portion of code then moves on to the next portion.n (no): Do not index the proposed portion of code, go to the next portion.s (split): split the proposed portion of code into a smaller portion if possibleq (quit): does not index the proposed portion of code, nor those remaining.
Sometimes the split command of git add -p fails to split hunks into smaller chunks (usually when changes follow each other). It is possible to switch to edit mode (e) in order to manually choose which part of the file you want to index.
Here's how to use the edit mode:
The Git editor offers you all the modified lines, prefixed by a symbol (i.e. context)
-indicates a deleted line- If you don't want this deleted row to be indexed, change the
contextfrom-to' '
- If you don't want this deleted row to be indexed, change the
+indicates an added line- If you don't want this added row to be indexed, delete it
- a modified line has two lines: the old (
-) and the new (+)- If you don't want this modified line to be indexed, delete the line indicated by
+and change thecontextof the deleted line from-to' '
- If you don't want this modified line to be indexed, delete the line indicated by
The idea is to create a version of your changes as you want them to appear in the index area. If modified lines should not be taken into account, restore their states for this
add -pas explained above. P.S: It is important not to touch the unmodified lines of the file!
Git offers a git stash command that allows you to put your changes aside and avoid dragging them around in the WD of other branches.
Here is a use case where the stash is useful:
- You are on a branch, feat/A, and you have made some modifications, still present in your WD.
- You must do a
git pullor agit rebase developon your branch: Git will refuse because you still have changes in your WD.
- Use the
git stashcommand to temporarily stash your changes - A new
stashentry is created. You can view yourstashlist viagit stash list - Do what you need to do (
pull, work on other branches, etc) - Use
git stash applyto apply the last createdstashon your WD
- Prefer
git stash applytogit stash popto keep your old stashes- Clean up via
git stash drop <stash>if somestashs are no longer useful- Use
git stash apply <stash>(example:git stash apply stash@{0}) to apply yourstashto the WD- Use
git stash -pto stash only part of your changes.
One or more conflicts may appear during a git merge, git rebase or even a git cherry-pick. This happens when the same line is modified on the 2 branches concerned by the command.
If you edit the conflicting file, you'll see how Git handles changes:
<<<<<<< HEADand=======encapsulate the modifications present initially=======and>>>>>>>encapsulate the new changes to integrate
- It's up to you to make your choice and delete obsolete modifications
Merging your modifications via these markers can be laborious. There are tools to help you manage conflict in a more visual way.
- See the list of supported merge tools default by Git
After downloading the tool of your choice:
- Tell Git how to use it:
git config --global merge.tool <tool>- You can have multiple tools configured and change the value of
merge.toolas needed
- You can have multiple tools configured and change the value of
- If this tool is not declared in your
$PATH, use the configurationgit config --global mergetool.<tool>.path <path> - You may not keep temporary files generated by Git during and after the conflict:
git config --global mergetool.keepBackup falsegit config --global mergetool.keepTemporaries false
- You're ready, invoke
git mergetoolduring conflicts to get Git to launch the visual editor for you!- Use
git commitand/orgit merge --continueto move to the next resolution - Use
git merge --abortto abort a conflict resolution
- Use
Reference logs or reflogs are a mechanism used by Git to record updates applied to branch tips (HEAD) and other commit references.
The reflog allows you to roll back commits even if they are not referenced by a branch or tag. Once the history is rewritten, the reflog contains information about the old state of the branches and allows you to return to it if necessary.
Every time you update your branch's HEAD tip for whatever reason (changing branches, pulling new changes, rewriting history, or just adding new commits), a new entry is added to the reflog.
- Consult the
reflogvia:git reflogto display thereflogof yourHEADgit reflog --relative-dateif you want to have a timestamped viewgit reflog --allto see thereflogof all your refsgit reflog <branch>to view thereflogof a particular branch
- Go back to the desired history state
git reset <reflog state>(example:git reset HEAD@{2})
A versioning platform relies on Git to offer you decentralized hosting of your source code and many other features (WYSIWYG, bug tracker, documentation, CI/CD, etc). These platforms offer remote repositories that will interact with your local repository via fetch, pull and push commands.
You can contact remote servers in two ways:
By entering your username and password (at each push or fetch)
- Set configuration
git config --global credential.helper cacheto avoid re-entry - You can define a personal-access-token which will be associated with your account and will replace your password when entering:
This personal-access-token should be used by your CI/CD tools so as not to directly use your account password
- For Github: https://help.github.com/en/articles/creating-a-personal-access-token-for-the-command-line
- For Gitlab: https://docs.gitlab.com/ee/user/profile/personal_access_tokens.html
- For Bitbucket: https://confluence.atlassian.com/bitbucketserver/personal-access-tokens-939515499.html
Authentication between your workstation and the platform will be carried out using your public SSH key, declared on the platform.
- Generate your SSH key if you don't already have one from a terminal (
Git Bashby default):ssh-keygen -t rsa -b 4096 -C "<your email>" - Leave the default build path:
~/.ssh/id_rsa - Enter (or not) a passphrase (which you will be asked for each
pushorfetch)- On Mac, your passphrase is saved automatically the first time you enter it
- For other systems, it is necessary to add your key to the ssh-agent:
ssh-add ~/.ssh/id_rsa
- Declare your public SSH key (
cat ~/.ssh/id_rsa.pub) on your platform:
Depending on the platform you are using, the terminology and workflow will be different but the concepts and principles remain the same.
Based on the chapter Typical workflow for development with Git:
- Do your development on a dedicated branch, making sure that the starting branch always stays in sync
- Publish your branch to the remote repository
- Create the merge request from the platform
- Depending on the result of the code review of your submission, either your branch will be integrated into
develop, or you will have to rework it before its integration.
###HEAD
HEAD is a pointer to the current branch reference, which is in turn a pointer to the last commit made on that branch. This means that HEAD will be the parent of the next commit to be created. It's usually easier to think of HEAD as the snapshot of your last commit.
Git uses other such references like
ORIG_HEAD: state of theHEADbefore agit resetFETCH_HEAD: state of the branch you just updated (viagit fetch)MERGE_HEAD: state of the branch after agit mergeCHERRY_PICK_HEAD: state of the branch after agit cherry-pick
The index is the area that contains the changes for the next commit you will make. This is the "stage area" powered by git add. This is what Git looks at when you run git commit.
Also called Working Tree, this is where you edit your files. You have to think of the working directory as a sandbox where you can try out your modifications before transferring them to your index and then committing them to your history, or throwing them in the trash (clean).
- Official Git documentation
- Visual Cheat Sheet
- GitFlow Workflow
- Become a git guru - Tutorials
- Commits Convention
- Merge vs. Rebase
- Git Reflog
This guide was written by Ludovic Dussart with the help of Gabin Darras in July 2019. Last updated July 2022.
Thanks to our reviewers: Kelsey Rider, Antoine Caron, Lucas Declercq, Mathias Deremer-Accettone, Pamela Rossignol, Emmanuel Peru, Clément Poissonnier.
Art direction and illustrations are the work of Jean-François Tranchida.
"I'm just a self-absorbed bastard, so I name all my projects after myself. First Linux, then Git." Linus Torvalds
Git (noun): an unpleasant or contemptible person.





