{"id":23738064,"url":"https://github.com/csmart/git_info","last_synced_at":"2026-01-30T14:18:07.266Z","repository":{"id":66656950,"uuid":"103926253","full_name":"csmart/git_info","owner":"csmart","description":null,"archived":false,"fork":false,"pushed_at":"2017-10-17T02:21:41.000Z","size":249,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-06-15T14:09:06.971Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":null,"has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/csmart.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2017-09-18T10:39:50.000Z","updated_at":"2022-12-06T23:59:05.000Z","dependencies_parsed_at":"2023-02-21T02:45:31.731Z","dependency_job_id":null,"html_url":"https://github.com/csmart/git_info","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/csmart/git_info","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/csmart%2Fgit_info","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/csmart%2Fgit_info/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/csmart%2Fgit_info/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/csmart%2Fgit_info/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/csmart","download_url":"https://codeload.github.com/csmart/git_info/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/csmart%2Fgit_info/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28913997,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-30T12:13:43.263Z","status":"ssl_error","status_checked_at":"2026-01-30T12:13:22.389Z","response_time":66,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-12-31T08:52:38.842Z","updated_at":"2026-01-30T14:18:07.255Z","avatar_url":"https://github.com/csmart.png","language":null,"funding_links":[],"categories":[],"sub_categories":[],"readme":"# Git\n\n\u003cimg src=\"/images/git_2x.png\" align=\"right\" width=\"400\" alt=\"If that doesn't \nfix it, git.txt contains the phone number of a friend of mine who understands \ngit. Just wait through a few minutes of 'It's really pretty simple, just think \nof branches as...' and eventually you'll learn the commands that will fix \neverything. https://xkcd.com/1597/\"/\u003e\n\n\u003c!-- vim-markdown-toc GFM --\u003e\n\n* [TLDR; Just show me how to use Git!](#tldr-just-show-me-how-to-use-git)\n* [About Git](#about-git)\n\t* [Additional resources](#additional-resources)\n* [Development methodology](#development-methodology)\n* [Installing Git](#installing-git)\n* [Setting Git defaults](#setting-git-defaults)\n* [Creating a repository](#creating-a-repository)\n* [Getting code from an existing repository](#getting-code-from-an-existing-repository)\n* [Working with Git](#working-with-git)\n\t* [Workspace - where you modify code](#workspace---where-you-modify-code)\n\t* [Staging area - where you prepare commits](#staging-area---where-you-prepare-commits)\n\t* [refs (references) - pointers to a commit](#refs-references---pointers-to-a-commit)\n\t* [HEAD - points to the branch in workspace](#head---points-to-the-branch-in-workspace)\n* [Remotes](#remotes)\n\t* [Referencing code directly in remotes](#referencing-code-directly-in-remotes)\n\t* [Adding a remote](#adding-a-remote)\n* [Branches](#branches)\n\t* [Local and remote branches](#local-and-remote-branches)\n\t\t* [Branch tracking information](#branch-tracking-information)\n\t* [Creating a local branch](#creating-a-local-branch)\n\t\t* [Creating backups](#creating-backups)\n\t* [Renaming a branch](#renaming-a-branch)\n\t* [Switching between branches](#switching-between-branches)\n* [What history looks like](#what-history-looks-like)\n\t* [Viewing the history](#viewing-the-history)\n\t* [Graphical log viewer](#graphical-log-viewer)\n\t* [View a commit](#view-a-commit)\n* [Making changes to the code](#making-changes-to-the-code)\n\t* [Adding a file](#adding-a-file)\n\t* [Making a change](#making-a-change)\n\t\t* [Viewing differences in the code](#viewing-differences-in-the-code)\n\t* [Committing a change](#committing-a-change)\n\t\t* [Writing a good commit message](#writing-a-good-commit-message)\n\t\t* [Amending a commit](#amending-a-commit)\n* [Modifying and squashing commits](#modifying-and-squashing-commits)\n\t* [Interactive rebase](#interactive-rebase)\n\t\t* [Delete commits](#delete-commits)\n\t\t* [Reorder commits](#reorder-commits)\n\t\t* [Squashing commits](#squashing-commits)\n\t\t* [Modifying a commit message](#modifying-a-commit-message)\n\t\t* [Modifying a commit](#modifying-a-commit)\n* [Getting recent updates](#getting-recent-updates)\n* [Sharing your changes](#sharing-your-changes)\n\t* [When pushing fails](#when-pushing-fails)\n\t\t* [Forcing a push](#forcing-a-push)\n\n\u003c!-- vim-markdown-toc --\u003e\n\n# TLDR; Just show me how to use Git!\n\nThis document is designed to provide just enough information to help you\n_understand_ the basics of Git.\n\nTo jump to a quick guide on how to use Git, see the [workflow\nexample](/workflow.md).\n\n# About Git\n\n[Git](https://git-scm.com/) is a Source Code Management (SCM) system, similar\nto other tools like Subversion, which helps you to keep track of your code over\ntime. Git supports common SCM features like branching, committing, merging and\ntagging.\n\nThere are some significant differences between Git and Subversion however, and\nit will take some time to get used to them. Hang in there though, the rewards\nare worth it!\n\nThe biggest core difference is that Git is _distributed_, not _centralised_.\n\nWith Subversion, there is a single repository where the code and its history is\nstored. No-one gets full direct access to the repository (except\nadministrators).  All SCM related commands like committing, branching, merging\nand even getting the log, are run across the network and on the central server.\n\nWith Git on the other hand, while there is generally a single blessed\nrepository sitting on a server somewhere (perhaps a project's GitLab account),\nevery user gets a full local copy of the repository by default. Each copy is\nequal.\n\nCommands like committing, branching, merging and even getting the log are run\n_locally_. Git does not touch the network unless you tell it to with one of a\nfew commands.\n\n* clone (get a local copy of a remote repository)\n* fetch (get the latest changes from a remote repository)\n  * pull (wraps fetch then does a merge)\n  * remote update (wraps fetch to get updates from all remotes)\n* push (push my local changes to a remote repository)\n\nWhy does that matter? It grants the user flexibility that is not otherwise\navailable, as you'll see below.\n\n## Additional resources\n\nThe Git website hosts the official open source [Pro Git\nbook](https://git-scm.com/book/) and\n[Tutorial](https://git-scm.com/docs/gittutorial), as well as a number of\n[useful links](https://git-scm.com/documentation/external-links).\n\nIf you're keen to try out Git in an online interactive tutorial, have a look at\nthe [one from GitHub](https://try.github.io/).\n\nThis repo has a [cheatsheet available](/cheatsheet.md) which provides many\ncommon Git commands, as well as a page on the [basic internals of\nGit](/internals.md), if you are interested.\n\n# Development methodology\n\nGit is very powerful and while it does not dictate a particular way of\nworking, there are some established best practices which will be very helpful.\nThese will be especially useful when working with other developers and\nmaintaining quality code.\n\nA common development approach is to perform all changes in a feature branch.\nOnce the changes are ready, generally following some sort of automated testing\nand code review, they are merged into the main code which is stored in the\n_master_ branch (which is like the _trunk_ branch in Subversion).\n\nFollowing this kind of model, developers do not commit directly to the master\nbranch. The idea behind this is that only approved, quality code lands in the\nmain branch that everyone else consumes.\n\nBranching is core to the fundamental design of Git, it was not added on at a\nlater stage.\n\nThe changes in a feature branch should have a neat commit history, with few\ncommits that are grouped together as appropriate. For example, aim to have a\nsingle commit for a feature, rather than dozens. This makes the history much\nmore clean and easier to work with in the future.\n\n# Installing Git\n\nGit is available for most platforms, including\n[Linux](https://git-scm.com/download/linux),\n[Windows](https://git-scm.com/download/win) and\n[MacOS](https://git-scm.com/download/mac).\n\nSee the appropriate link above for your platform (but we'll assume you're using\nLinux).\n\n# Setting Git defaults\n\nOnce you have Git, you should set some global default settings. Setting these\ncan be done by running the config command which writes to the .gitconfig file\nin your home directory (on Linux at least). You can also just edit that file\ndirectly, if you know what settings to change (see _git config --help_).\n\nNote that these settings can be overridden on a per-repository basis by\nomitting the _--global_ option when run inside the workspace.\n\n```bash\n# Tell Git the default name to use\ngit config --global user.name \"Full Name\"\n\n# Tell Git the default email address to use\ngit config --global user.email \"email address\"\n\n# Colorise Git output\ngit config --global color.ui auto\n\n# Set vim as the default editor\ngit config --global core.editor /usr/bin/vim\n\n# Use 16 chars for short commit hashes\ngit config --global core.abbrev 16\n```\n\n# Creating a repository\n\nGit is distributed and anyone can create a local repository.\n\nSimply provide the name of a directory which you wish to turn into a Git repo\n(this can already have files in it) and initialise it!\n\n```bash\ngit init /path/to/directory\n```\n\nThe directory is now an empty repository, as nothing is being tracked by Git\nyet. We will see how to add and commit files soon.\n\nFor those who are curious, your Git repository actually lives in a hidden\ndirectory _.git_ in this parent directory. If you delete this directory, you\nwill lose your Git history!\n\n# Getting code from an existing repository\n\nOften you aren't creating your own local repository but instead want a copy of\none that already exists. This follows a different process.\n\nWith Subversion, you get a copy of the code at a particular point in time via\nthe _checkout_ command which is run against the central server. This is not the\nfull history, just the code at that point in time and is generally a branch or\na tag. Each time a developer wants a different tag or branch, they perform a\ncheckout again into a different directory.\n\nWith Git however, you _clone_ just one copy of the entire repository from a\nremote location. This is generally from a server (like GitLab) via SSH, but\ncan be via other protocols like Git, HTTPS, or even a local file system.\n\nThe method you use to clone the repository will depend on what protocols the\nserver provides.\n\n```bash\n# This uses SSH\ngit clone user@server:/path/to/code /path/for/local/code\n\n# This uses HTTPS\ngit clone https://user@server/path/to/code /path/for/local/code\n```\n\n# Working with Git\n\nGit has the following core concepts which are useful to know.\n\n| Concept | Purpose |\n| --- | --- |\n| workspace | Local directory where you modify files in the branch you have checked out. |\n| staging area | Virtual place where you prepare commits before committing them. |\n| refs (references) | Point branches and tags to a commit. |\n| HEAD | A special reference to the latest commit for the branch in workspace. |\n\n## Workspace - where you modify code\n\nWhile a clone gets a full copy of the repository, by default Git will checkout\na copy of the _master_ branch into the directory specified at the end of that\ncommand.\n\nThis is called your _workspace_ and is where you access and modify the contents\nof the branch.\n\nIf you initialised a new repository in your current local directory, you're\nalready in your workspace. Else, you need to _cd_ into that directory.\n\nYou can check the status of your workspace by running the status command.\n\n```bash\ngit status\n```\n\nThis will print the branch and commit information, show you any files which are\nnot tracked, and any files which have been changed but not committed.\n\nWe will see how to manage branches shortly.\n\n## Staging area - where you prepare commits\n\nBefore you can _commit_ any modified files in your workspace, they must be\nadded to the _staging area_ in the Git repository.\n\nThis is a special Git feature that lets you craft what a commit will look like\nfrom the files you've modified. When you do a commit, only changes which have\nbeen staged will be committed.\n\nThis lets you perform multiple and/or different changes, but group them in\nseparate commits.\n\nTo put a file into the staging area, you _add_ it.\n\n```bash\n# Add README.me to the staging area\ngit add README.md\n```\n\nYou can even add just _parts_ of a changed file, in selectable chunks. This can\nbe useful when you've made lots of changes in the workspace but don't want them\nall to go into the current commit.\n\n```bash\n# Add just _parts_ of a changed file\ngit add --patch README.md\n```\n\nYou can see which files you've staged with the _status_ command, and see the\nchanges with _diff --cached_ command.\n\n## refs (references) - pointers to a commit\n\nIn Subversion, a branch or tag is a full copy of the repository (usually done\nwith hardlinks).\n\nIn Git, a branch or tag just references a commit in the project history (this\nis why branching is so cheap!).\n\nThese refs files are usually the name of a branch or tag and are stored under\nthe _.git/refs/_ directory in the repository.\n\nSo when you refer to a branch like _master_ this is actually just a pointer to\na commit. Git knows which commit by reading the refs file called _master_.\n\n```bash\n# See the content of the refs file for local master branch\ncat .git/refs/heads/master\n\n# Use Git to parse the ref for local master branch\ngit rev-parse refs/heads/master\n```\n\n## HEAD - points to the branch in workspace\n\nThere's a special reference in Git called _HEAD_. It points to the latest\ncommit on the branch you have checked out in your workspace.\n\nYou can use this to refer to the latest commit in your workspace when\nperforming Git commands, or commits relative to HEAD.\n\n| Reference | Location |\n| --- | --- |\n| HEAD | The latest commit |\n| HEAD^ | One commit back from HEAD |\n| HEAD^^ | Two commits back from HEAD |\n| HEAD~9 | Nine commits back from HEAD |\n\n```bash\n# See what branch HEAD is pointing to (probably master)\ngit symbolic-ref HEAD\n\n# We can parse the ref and see what commit HEAD is pointing to\ngit rev-parse HEAD\n```\n\n# Remotes\n\n**This is where Git _really_ starts to differ from other tools like Subversion.**\n\nIn Subversion there is only one remote. You don't even really think about it\nbecause any operations must automatically talk to the remote server.\n\nGit is distributed and it's not tied to a remote server. It lets you talk to\n_any number of remotes in different locations_ that have a copy of the same\ncode base.\n\nIf you cloned a repository rather than initialising one locally, Git will\nremember the location that you initially cloned from.\n\nThis is called a _remote_ and Git gives it the name _origin_.\n\nSee your remotes with the following command:\n\n```bash\ngit remote -v\n```\n\nYou might want to use more than one remote if you have cloned your own copy of\nthe code from a local server when there's also an upstream version elsewhere.\n\nBecause you can have more than one, _Git needs to know which remote you want to\ntalk to_ when you perform a network operation.\n\nMore about that soon!\n\n## Referencing code directly in remotes\n\nFurthermore, you can also _reference remotes directly_ when you want to look at\ncode.\n\n* master - this is your local master branch\n* origin/master - this is the master branch on the remote called origin\n\nYour local branch master is completely separate entity to the master branch on\nthe remote. You can have local commits on your master that do not exist on any\nof the remote master branches.\n\nIf you want to refer to the latest code on the remote, then use the remote name\nprefix like origin/master.\n\n## Adding a remote\n\nAdding a second remote pointing to the upstream version would let you fetch the\nchanges from upstream and merge them into your local repository. This is part\nof the power of distributed SCM and it might take a while to get your head\naround.\n\nYou can easily add another remote, but the name must be unique (i.e. it can't\nbe called _origin_).\n\n```bash\ngit remote add upstream user@another-server:/path/to/code\n```\n\nYou should be able to list your remotes again as above and see two.\n\nThis is useful to know because many network based Git commands need to know\nwhich remote server you want to talk to. Most of the time this will be\n_origin_.\n\nMore on that soon.\n\n# Branches\n\nIn Subversion, you have a one to one relationship between the code on the\nserver and the local copy of it in your workspace. You check out one branch or\ntag into one local directory.\n\nIn Git, remembering that you have a full copy of the repository, you _switch_\nbetween branches in the same workspace.\n\nThis is a very big difference in the way Git and Subversion work and it's\nsomething that will take some getting used to.\n\nBy default your workspace will have a checked out copy of the _master_ branch.\n\n## Local and remote branches\n\nIn Subversion, branches only really exist on the remote server.\n\nIn Git, branches exist in both your local and the remote repositories, although\nyou might never have actually checked out a branch locally. Due to Git's\ndistributed nature however, you can also have your own local branches which are\nnot on the remote.\n\nRemember that any branching or merging is a local affair unless you push your\nchanges to a remote!\n\nNote that you can see some extra information about the branch if you specify\nthe --verbose option, like the latest commit on the branch.\n\n```bash\n# See local branches\ngit branch --verbose\n\n# See available remote branches\ngit branch --verbose --remotes\n\n# See all branches:\ngit branch --verbose --all\n```\n\n### Branch tracking information\n\nRemember how in Git you can have multiple branches and multiple remotes? Enter\n(optional) tracking!\n\nTracking information specifies which branch on which remote server your local\ncopy of the branch is set to follow by default. This means if you told Git to\njust push or fetch the latest changes without specifying the remote or branch,\nit will do so from the branch it is tracking.\n\nYou can see the tracking information for the local branch you're in by adding\nsome extra verbosity to the branch command!\n\n```bash\ngit branch --verbose --verbose\n```\n\n## Creating a local branch\n\nCreating a local branch is as simple as telling Git what name you want to give\nthe branch and where it should branch from (by default this is from the branch\nyou currently have checked out).\n\nFor example, you can create a branch called _mybranch_ from the tip of your\nlocal master branch like so.\n\nNote that if your local master is behind you may want to [update it\nfirst](#getting-recent-updates) to get the latest changes from the remote\nbranch.\n\n```bash\ngit branch mybranch master\n```\n\nIt may be better to create your branch from the latest code on the remote, as\nyour local branch may not be up-to-date or have different commits.\n\nSimply add the remote name prefix.\n\n```bash\ngit branch mybranch origin/master\n```\n\nBranches are extremely cheap because they are actually just a file which points\nto a unique commit in the Git history. No duplication of files is done.\n\n### Creating backups\n\nBecause branches are so cheap, it's a really nice way to create a local backup\nof a branch. This way you can always get your original branch back to the way\nit was before you tried something tricky, like a _rebase_.\n\n```bash\ngit branch mybranch-backup mybranch\n```\n\n## Renaming a branch\n\nGiven that a branch is just a file which points to a commit, renaming branches\nis done by simply moving the branch to a new name.\n\n```bash\ngit branch --move oldbranch newbranch\n```\n\n## Switching between branches\n\nRemember that Git has a full copy of the repository but only one copy of the code\nis accessible at any point in time in your workspace. By default this is the\nmaster branch, but we've shown how you can create as many branches as you like.\n\nWe also mentioned that unlike Subversion, you just switch your workspace\nbetween branches.\n\nThis is done with the _checkout_ command.\n\n```bash\ngit checkout mybranch\n```\n\nThis will cause your workspace to switch the contents from the current branch\nto the new branch you specified.\n\nEverything is changed on disk automatically.\n\nIf your workspace is clean, you should not have any trouble switching between\nbranches.\n\nIf you have made changes to your local files but not yet committed them, those\nchanges will be maintained in your workspace when you switch branches.\n\nNote however, that there might be conflicts if the changes you've made are\ndrastically different to those in the other branch. In this case, you just need\nto fix up any conflicts.\n\n# What history looks like\n\nYou will just see your repository as a series of commits with a bunch of\nassociated data. If you have more than one branch, you'll see that information\ntoo. The history looks a lot like it does in any other SCM tools.\n\n\nA flat history of the master branch will look something like this, with oldest\ncommit at the bottom.\n\n```bash\n* 602083f0da6aacac (HEAD -\u003e master) Second set of changes\n|\n* 22b56bb62019c7b8 First set of changes\n|\n* 0d5dbcf6eac9a558 Initial commit in master branch\n```\n\nGenerally a history where work is done in branches and merged to master will\nlook something like this.\n\n```bash\n*   cef3f6b8bab5a556 (HEAD -\u003e master) Merge branch 'otherbranch'\n|\\\n| * 4c05b05ba3e0fda6 (otherbranch) Second set of changes in otherbranch\n|/\n*   b1d3234a14c1c8b8 Merge branch 'mybranch'\n|\\\n| * d9b81ddb5636ba24 (mybranch) First set of changes in mybranch\n|/\n* 0d5dbcf6eac9a558 Initial commit in master branch\n```\n\n## Viewing the history\n\nSimilar to Subversion, you can view the log (or history) of the repository.\nThis can be the full history, or just a range. By default this is run against\nthe branch you have checked out in your workspace.\n\n```bash\n# Full commit messages\ngit log\n\n# Get log in a range\ngit log \u003ccommit\u003e...\u003ccommit\u003e\n```\n\nHowever you can also check the log from any branch, local or remote, or even\nfrom a specific commit in the history.\n\n```bash\ngit log origin/master\n```\n\nGit also lets you do lots of fancy, tricky things with the log too, like\nshowing all commits by a specific author.\n\n```bash\n# Commits by name\ngit log --author=\"Full Name\"\n\n# Commits by email address\ngit log --author=\"email address\"\n```\n\nGit supports a [pretty format](https://git-scm.com/docs/pretty-formats)\nthat has some options like _oneline_, _short_ and _stat_.\n\n```bash\n# Statistics with the commit, like number of lines changed\ngit log --stat\n\n# One line commit messages\ngit log --oneline\n```\n\nIt can also graph the relationship between all branches, and decorate the\noutput.\n\n```bash\n# Graph relationship between all branches\ngit log --oneline --graph --decorate --all\n```\n\nGit also supports custom _formats_ to show anything you like, which you can\ncombine with options like _graph_.\n\n* Show the branch interactions\n* Commit hash\n* Branch a commit came from\n* One line commit message summary\n* How long ago the commit was made\n* Who made the commit\n\n```bash\ngit log \\\n--graph \\\n--abbrev-commit \\\n--pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)\u003c%an\u003e%Creset'\n```\n\nGit log is really powerful.\n\n## Graphical log viewer\n\nSometimes you might want a graphical view of the history. GitLab can do this\nfor you or you can use command line tools like [gitk (open\nsource)](https://git-scm.com/docs/gitk) or [GitKraken\n(proprietary)](https://www.gitkraken.com/).\n\n## View a commit\n\nYou can view any number of commits by using the _show_ command with one or more\ncommit hashes. This will show you the change itself and accompanying metadata\nsuch as commit message, author and date.\n\n```bash\ngit show \u003chash\u003e [\u003chash\u003e]\n```\n\n# Making changes to the code\n\nSo now we're ready to change the code.\n\n## Adding a file\n\nBefore you can commit a change however, Git must be tracking the file. Like\nSubversion, this is an _add_ command.\n\n```bash\ngit add file\n```\n\nFrom now on, Git will track the contents of this file and include it in the\ncommit.\n\nUnlike Subversion, each time you want to commit a change, the file must be\nre-added. This is because Git has an awesome feature called the staging area\nwhere you can gather up changes before they are committed.\n\nThis allows you to do things like add specific _parts_ of a larger change into\na commit, rather than the entire change.\n\nWe'll re-visit this some more below.\n\n## Making a change\n\nYou can make changes to tracked files in your workspace.\n\n### Viewing differences in the code\n\nYou can view the differences between any two points in the Git history or\nworkspace.\n\nBy default, the _diff_ command will compare your workspace with the latest\ncommit in the branch you're on.\n\n```bash\ngit diff\n```\n\nIf you have added some files to the staging area, you won't see these unless\nyou add the --cached option.\n\n```bash\ngit diff --cached\n```\n\nIt gets more interesting than that, you can compare your workspace with the\nlatest changes in a branch (including remotes) or with a commit at any point\nin time.\n\n```bash\n# Compare workspace with remote branch\ngit diff remote/branch\n\n# Compare workspace with another commit\ngit diff \u003ccommit\u003e\n\n# Compare two branches\ngit diff branch other/branch\n```\n\n## Committing a change\n\nWhen you commit a change using Subversion, it is a centralised event.\nYou make a change to a file and when you commit it, the change is sent to the\nserver and a commit record is made. This change is then inherited by everyone\nelse using that branch in Subversion.\n\nCommits in Git are local. They are not sent to a remote server unless those\ncommits are pushed.\n\nTo make a change, just edit a file in your workspace that Git is tracking (has\npreviously been added).\n\nThe status command should show that your workspace has a change that is \"not\nstaged for commit.\"\n\n```bash\ngit status\n```\n\nTo stage them, as discussed above we _add_ them.\n\n```bash\ngit add file\n```\n\nNow status should tell you there are \"changes to be committed.\"\n\nNext, you can commit these changes which will prompt you for a commit message.\n\n```bash\ngit commit\n```\n\nType in your commit message. If you need to change the default text editor, you\ncan set this in your ~/.gitconfig.\n\n### Writing a good commit message\n\nQuality, informative commit messages are really valuable.\n\n\u003cimg src=\"/images/git_commit_2x.png\" width=\"400\" alt=\"Merge branch \n'asdfasjkfdlas/alkdjf' into sdkjfls-final https://xkcd.com/1296/\"/\u003e\n\nIn general, good commit messages should follow a pattern like so.\n\n- Start with a short description of the problem, less than 50 chars. Ideally\n  this should also reference the area of the code the change applies to.\n- In a new paragraph, describe the problem or feature the patch is addressing\n  using lines of no more than 72 characters.\n- In a new paragraph, describe how the patch solves or implements the above.\n- Add any other notes relating to the patch (like how to test it).\n- If related tickets, merge requests or snippets exist in GitLab, they can be\n  referenced.\n\nHere is an example commit message.\n\n```\nreadme: added authors to the readme\n\nThere were other authors that were contributing to this code, however they were\nleft off the AUTHORS section in the README.md.\n\nThis patch adds these authors so that their work is attributed.\n\nRelated to #123, fixes #456 and closes group/otherproject#22.\n\nSee merge request !123 and related snippet $123.\n```\n\nThe first line summary is particularly useful because Git lets you format logs\non just one line, which is helpful for quickly finding a commit.\n\n### Amending a commit\n\nIf you've made a commit but later you wish to modify it (without making a new\ncommit on top) you can amend it. This is generally not a good idea if you are\nworking collaboratively on a branch as it will re-write the history of the\nproject (the commits will change and be different for other developers).\n\nThe only difference between this and making a regular new commit, is adding the\n_--amend_ option to the _commit_ command.\n\nSo simply make your changes as usual, add the file (or part thereof) and then\nwhen you run the _commit_ add the _--amend_ option.\n\n```bash\ngit commit -a --amend\n```\n\nNote that this will re-write the history. The new change will be squashed into\nthe new commit and you will have a new commit hash.\n\nThis means that if you try to push the change, Git will warn you that the\nhistories have diverged and suggest you do a pull to get the latest changes.\n\nIf you're amending, you don't want to do that, you just want to force push.\n\n# Modifying and squashing commits\n\n\u003cimg src=\"/images/danger.jpg\" align=\"left\" width=\"200\" alt=\"Danger, Will\nRobinson, Danger!\"/\u003e\n\nGit lets you modify your existing commits in a number of ways, via an\ninteractive _rebase_ command. This is one of the most amazing, useful, yet\noften misunderstood features in Git.\n\n* p, pick = use commit\n* r, reword = use commit, but edit the commit message\n* e, edit = use commit, but stop for amending\n* s, squash = use commit, but meld into previous commit\n* f, fixup = like \"squash\", but discard this commit's log message\n* x, exec = run command (the rest of the line) using shell\n* d, drop = remove commit\n\nIt can easily get you into trouble as it will change and re-write your branch\nhistory, so consider [creating a backup\nbranch](/tips.md#make-a-local-backup-branch) before you use rebase.\n\n**WARNING:** In general, you should not change the history for branches that\nhave already been made public, in particular the master branch. This will break\neveryone else's copy of the branch and create problems for any other feature\nbranches that are in progress.\n\nHowever, rebase is a really great tool for your own feature branches. It\nprovides a way to group and tidy up commit history before your branch is merged\ninto master.\n\n## Interactive rebase\n\nBefore you can change history, you need to perform an interactive rebase and\nprovide Git with a commit range.\n\nFor example, you go from HEAD (the latest commit on the branch in your\nworkspace) back two commits, you could do this.\n\n```bash\ngit rebase --interactive HEAD~2\n```\n\nThis will put you into a menu where you can see the three commits listed with\noptions for the rebase command you want to perform (see above).\n\n### Delete commits\n\nTo delete a commit you can simply delete the line, then save and exit the\nrebase file.\n\nAlternatively, change _pick_ to _drop_, then save and exit the rebase file.\n\n### Reorder commits\n\nA simple rebase task is to simply re-order the commits. All you need to do is\nmove the lines into the new order you want.\n\nKeep in mind that you may encounter conflicts which you need to fix. There may\nbe code missing which means that Git can't apply the patch.\n\n### Squashing commits\n\nYou can squash multiple commits together and keep their commit messages by\nfinding the first commit you want to keep and leaving it at _pick_.\n\nNow go to the next commit(s) you want to squash together and change _pick_ to\n_squash_.\n\nSave and close the rebase file and Git will prompt you for a new commit\nmessage. By default this will be the combination of the commits. Once you're\nhappy with your new combined commit message, save and quit the file and Git\nwill squash the commits together into one.\n\nIf you are happy to discard any of the other commit messages you can use _fixup_\ninstead of _squash_ and they will be automatically discarded.\n\n### Modifying a commit message\n\nChange _pick_ to _reword_ for the commit message(s) you want to re-write then save\nand close the rebase file.\n\nYou can then edit each commit message one by one.\n\n### Modifying a commit\n\nChange _pick_ to _edit_ for the commit(s) you want to edit then save and\nclose the rebase file.\n\nGit will take your workspace back to each commit in turn.\n\nModify files as you see fit, add them, then continue the rebase.\n\n```bash\nvim README.md\n\ngit add README.md\n\ngit rebase --continue\n```\n\n# Getting recent updates\n\nWhen you're working on a branch that is going to go into master, often master\nwill move ahead before you're ready to merge your new changes in.\n\nWhile you can keep working, if you ignore the changes in master, you may get\nconflicts when you try to merge the branch into master later.\n\nTo get the latest changes in, you can do two things, merge or rebase.\n\nIf you're working on your own branch, rebase is the cleanest method as it takes\nyour changes off, adds the new commits from master and replays your changes\nback on top.\n\nThis way it's like you just branched from master today!\n\nIf you have to fix up any conflicts, these just become part of your series of\nchanges, not a special merge commit later that goes onto master. This makes\nlife much easier when working on code with others.\n\n```bash\ngit pull --rebase origin master\n```\n\nThis also works if you're working on a feature branch collaboratively. If\nsomeone has made a change to your branch, just rebase their changes onto yours,\nand push.\n\n# Sharing your changes\n\nOnce you have committed local changes to a branch, you can push it to a\nremote server.\n\nGenerally you should tell Git which remote you want to push to and which branch\n(even though you have a local branch checked out, you might not want to push\nit!).\n\n```bash\ngit push origin mybranch\n```\n\nIf you want to set or update the tracking information for your local branch to\nthe remote location you are pushing, you can tell it to do so.\n\n```bash\ngit push --set-upstream origin mybranch\n```\n\nOnce your branch is set up to track a remote branch you can leave those details\noff.\n\n```bash\ngit push\n```\n\n## When pushing fails\n\nIf other users have committed changes to the branch you are pushing to, the\nremote copy of the branch will have extra commits that your local copy does not\nhave.\n\nIf you try to push your branch, Git will report an error because there are\ndiverged paths. That is to say, your local branch has different commits to the\nremote, even though they share a common parent commit.\n\nGit will ask you to deal with this and try your push again.\n\nYou have two main choices:\n\n - Fetch and merge in the changes that exist on the remote server.\n - Fetch the changes that exist on the remote server and replay your changes on\n   top.\n - Replace the remote changes with your own (this removes those remote commits).\n\nGit will recommend that you do a pull to get the most recent changes. This is\nthe most common way to pull in changes that have gone upstream.\n\n\n### Forcing a push\n\nGenerally, if you are working on your own branch and have done a rebase from\nanother branch, or amended a commit you're safe to force push.\n\nIf you are working collaboratively, then you need to consider whether force\npushing is correct - it may remove genuine changes other developers have\npushed.\n\nTo force a push add the --force command line option to the push command:\n\n```bash\ngit push --force\n```\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcsmart%2Fgit_info","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fcsmart%2Fgit_info","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fcsmart%2Fgit_info/lists"}