{"id":18523001,"url":"https://github.com/avine/git-cheat-sheet","last_synced_at":"2025-05-14T18:32:41.159Z","repository":{"id":120339973,"uuid":"123737799","full_name":"avine/git-cheat-sheet","owner":"avine","description":"Simple GIT commands that produce a clean log history","archived":false,"fork":false,"pushed_at":"2021-03-01T16:12:19.000Z","size":18,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":3,"default_branch":"master","last_synced_at":"2024-11-06T17:50:02.358Z","etag":null,"topics":["cheat-sheet","commands","git","tutorial"],"latest_commit_sha":null,"homepage":"","language":"Shell","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/avine.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","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}},"created_at":"2018-03-03T22:45:18.000Z","updated_at":"2021-03-01T16:12:21.000Z","dependencies_parsed_at":null,"dependency_job_id":"f313e256-54e7-4d90-bae2-fcc1cb60837b","html_url":"https://github.com/avine/git-cheat-sheet","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/avine%2Fgit-cheat-sheet","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/avine%2Fgit-cheat-sheet/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/avine%2Fgit-cheat-sheet/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/avine%2Fgit-cheat-sheet/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/avine","download_url":"https://codeload.github.com/avine/git-cheat-sheet/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":239238363,"owners_count":19605276,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","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":["cheat-sheet","commands","git","tutorial"],"created_at":"2024-11-06T17:33:50.999Z","updated_at":"2025-02-17T05:26:18.448Z","avatar_url":"https://github.com/avine.png","language":"Shell","readme":"# git-cheat-sheet\n\nSimple GIT commands that produce a clean log history\n\n## Initialize repository\n\n*Create local repo:*\n\n```bash\n# create new folder and navigate into it\nmkdir myrepo\ncd myrepo\n\n# init local repo with branch called \"master\"\ngit init\n\n# at this point, you should configure your user name and email (see below for details)\n\n# create and commit file\ntouch README.md\ngit add README.md\ngit commit --message \"First commit\"\n\n# configure url of remote repo called \"origin\"\ngit remote add origin https://github.com/myuser/myrepo.git\n\n# check added remote\ngit remote --verbose\n\n# push local branch \"master\" to remote repo \"origin\"\ngit push --set-upstream origin master\n```\n\n*Or clone existing remote repo locally:*\n\n```bash\n# clone remote repo\ngit clone https://github.com/myuser/myrepo.git\n\n# navigate to local repo\ncd myrepo\n\n# check that remote is already configured\ngit remote -v\n```\n\n## User configuration\n\nConfigure user name and email before commiting.\n\n```bash\ngit config user.name \"Stéphane Francel\"\ngit config user.email contact@avine.io\n```\n\n## Status and log\n\nView the repo status and history.\n\n```bash\ngit status\ngit log --oneline --graph --decorate\n```\n\n## Staging and unstaging files\n\n*For new untracked file:*\n\n```bash\n# creating new untracked file...\ntouch foo.txt\n\n# add file to the index (tracking and staging)\ngit add foo.txt\n\n# untrack file (use `git reset` without argument to reset all changes)\ngit reset -- foo.txt\n```\n\n*For already committed file:*\n\n```bash\n# modify file previously committed\necho \"More Foo...\" \u003e\u003e foo.txt\n\n# staging the changes\ngit add foo.txt\n\n# unstage the file but keep the changes\ngit reset -- foo.txt\n\n# discard changes (ONLY for unstaged file)\ngit checkout -- foo.txt\n```\n\nNote: you must unstage a file before discarding its changes.\n\n## Discard all changes (staged on not)\n\n```bash\n# modify multiple files\necho \"Foo...\" \u003e\u003e foo.txt\necho \"Bar...\" \u003e\u003e bar.txt\n\n# staging one of them\ngit add foo.txt\n\n# restore the working tree to HEAD\ngit reset --hard\n```\n\n## Delete file from the index and the working tree\n\n```bash\n# delete unmodified file from the index and the working tree\ngit rm foo.txt\n\n# modify file\necho \"More Bar...\" \u003e\u003e bar.txt\n\n# delete modified file (staged or not) from the index and the working tree\ngit rm --force bar.txt\n```\n\n## Delete file from the index but keep it in the working tree\n\n```bash\n# delete file (modified or not, staged or not) from the index but keep it in the working tree\ngit rm --cached foo.txt\n```\n\nAfter that, the file will be marked as untracked.\n\n## Commit changes and amend last commit before push\n\n```bash\n# modify file\necho \"Hello\" \u003e\u003e foo.txt\n\n# staging file\ngit add foo.txt\n\n# commit changes with message\ngit commit --message \"Hello World!\"\n\n# oups! we forgot something!\necho \"World!\" \u003e\u003e foo.txt\n\n# staging file\ngit add foo.txt\n\n# amend the last commit (without modifying the message)\ngit commit --amend --no-edit\n\n# push modified commit to the remote server safely\ngit push\n```\n\n## Amend last commit after push\n\n```bash\n# push some previous commit to the remote server\ngit push\n\n# oups! we forgot something!\ntouch baz.txt\necho \"Baz...\" \u003e baz.txt\ngit add baz.txt\n\n# adding baz.txt to the last commit\ngit commit --amend --no-edit\n\n# overwrite the history on the remote server\ngit push --force\n```\n\n\u003e Do this ONLY if you DON'T work with a team!\n\n## Amend last commit author\n\n```bash\ngit commit --amend --author \"John Doe \u003cjohndoe@avine.io\u003e\"\n```\n\n## Create and delete branches\n\n```bash\n# list all branches\ngit branch --all\n\n# create new branch of master\ngit branch feature-one master\n\n# checkout existing branch\ngit checkout feature-one\n\n# or create and checkout new branch at once!\ngit checkout -b feature-one master\n\n# delete a fully merged branch\ngit branch --delete feature-one\n\n# delete a branch whether merged or not\ngit branch --delete --force feature-one\n```\n\n## Rebase and merge branches\n\n### Using \"no fast forward\" strategy\n\nAssuming someone works on `feature-one`.\n\n```bash\n# clone repo and checkout new branch\ngit clone https://github.com/myuser/myrepo.git\ngit checkout -b feature-one\n\n# create new file\ntouch fruits.txt\n\n# modify, add and commit\necho \"Orange\" \u003e fruits.txt\ngit add fruits.txt\ngit commit -m \"Add Orange\"\n\n# modify, add and commit again (option -am works for already tracked file)\necho \"Banana\" \u003e\u003e fruits.txt\ngit commit -am \"Add Banana\"\n```\n\n*Log history of branch `feature-one`:*\n\n```txt\n$ git log --oneline --graph --decorate\n* 484dbf6 (HEAD -\u003e feature-one) Add Banana\n* c7fc421 Add Orange\n* 0285f89 (origin/master, origin/HEAD, master) Initial commit\n```\n\nMeanwhile, someone else was working on `feature-two`...\n\n```bash\ngit clone https://github.com/myuser/myrepo.git\ngit checkout -b feature-two\n\ntouch technos.txt\n\necho \"NodeJs\" \u003e technos.txt\ngit add technos.txt\ngit commit -m \"Add NodeJs\"\n\necho \"Java\" \u003e\u003e technos.txt\ngit commit -am \"Add Java\"\n```\n\n*Log history of branch `feature-two`:*\n\n```txt\n$ git log --oneline --graph --decorate\n* 64364db (HEAD -\u003e feature-two) Add Java\n* 120e8c2 Add NodeJs\n* 0285f89 (origin/master, origin/HEAD, master) Initial commit\n```\n\nNext, the first developer is pushing his work.\n\n```bash\n# leave branch feature-one and go back to branch master\ngit checkout master\n\n# merge feature-one into master (with no-fast-forward)\ngit merge feature-one --no-ff -m \"Merge feature-one\"\n\n# push commits to remote origin\ngit push origin\n```\n\n*Log history of branch `master`:*\n\n```txt\n*   0f6ca39 (HEAD -\u003e master, origin/master, origin/HEAD) Merge feature-one\n|\\\n| * 484dbf6 (feature-one) Add Banana\n| * c7fc421 Add Orange\n|/\n* 0285f89 Initial commit\n```\n\nNow, how can the other developer (who worked on `feature-two`) also push his work ?\n\n```bash\n# while staying on the branch feature-two, get branch master\n# up-to-date and merged into the current branch\ngit pull --rebase origin master:master\n\n# the previous command is equivalent to:\n#   git checkout master\n#   git pull --rebase origin\n#   git checkout feature-two\n#   git rebase master\n\n# back to branch master, merge feature-two into master (with no-fast-forward)\ngit checkout master\ngit merge feature-two --no-ff -m \"Merge feature-two\"\n\n# push commits to remote origin\ngit push origin\n```\n\n*Log history of branch `master`:*\n\n```txt\n$ git log --oneline --graph --decorate\n*   8e5a570 (HEAD -\u003e master, origin/master, origin/HEAD) Merge feature-two\n|\\\n| * 0aa4f57 (feature-two) Add Java\n| * 1ad2fe8 Add NodeJs\n|/\n*   0f6ca39 Merge feature-one\n|\\\n| * 484dbf6 Add Banana\n| * c7fc421 Add Orange\n|/\n* 0285f89 Initial commit\n```\n\nSo, always merging branches with no-fast-forward option, ensures that each feature has a merge commit.\n\nThis is usefull because we can quickly get a summary of what has been developed so far on branch master using `git log --merges`.\nThis way, we skip the intermediate commits and focus on the list of features.\n\n```txt\n$ git log --oneline --graph --decorate --merges\n* 8e5a570 (HEAD -\u003e master, origin/master, origin/HEAD) Merge feature-two\n* 0f6ca39 Merge feature-one\n```\n\nWithout rebasing from master before merging, the log history will not have been so clean!\n\n*Log history without rebasing:*\n\n```text\n$  git log --oneline --graph --decorate\n*   518d342 (HEAD -\u003e master, origin/master, origin/HEAD) Merge feature-two\n|\\\n| * 36b9e38 (feature-two) Add Java\n| * 6acf6ba Add NodeJs\n* |   cdc7ce7 Merge feature-one\n|\\ \\\n| |/\n|/|\n| * fa1df45 Add Banana\n| * 6de9efd Add Orange\n|/\n* 0285f89 Initial commit\n```\n\n### Using \"fast forward only\" strategy\n\nAnother strategy you can choose is to always use `git merge --ff-only` instead of `git merge --no-ff`\n\nIf you redo from the begining the commands of the previous section using this strategy then you'll get a single line of history on the branch master.\n\n```txt\n$ git log --oneline --graph --decorate\n* eee05a6 (HEAD -\u003e master, origin/master, origin/HEAD, feature-two) Add Java\n* 4801abf Add NodeJs\n* 8ec6840 Add Banana\n* cc3fdad Add Orange\n* 0285f89 Initial commit\n```\n\n### Using \"squash commits\" strategy\n\nAnother strategy you can choose is to squash all commits in a feature branch into a single commit.\n\n*Let's say that the log history is as following:*\n\n```txt\n$ git checkout master\n\n$ git log --oneline --graph --decorate\n* 0285f89 (origin/master, origin/HEAD, master) Initial commit\n\n$ git checkout feature-one\n\n$ git log --oneline --graph --decorate\n* 484dbf6 (HEAD -\u003e feature-one) Add Banana\n* c7fc421 Add Orange\n* 0285f89 (origin/master, origin/HEAD, master) Initial commit\n\n$ git checkout feature-two\n\n$ git log --oneline --graph --decorate\n* 64364db (HEAD -\u003e feature-two) Add Java\n* 120e8c2 Add NodeJs\n* 0285f89 (origin/master, origin/HEAD, master) Initial commit\n```\n\n*Let's go to branch `feature-one` and start interactive rebase.*\n\n```txt\n$ git checkout feature-one\n$ git rebase --intercative master\n```\n\n*This will open up your editor with the following file content:*\n\n```txt\npick c7fc421 Add Orange\npick 484dbf6 Add Banana\n```\n\n*Change the file to this:*\n\n```txt\npick c7fc421 Add Orange\nsquash 484dbf6 Add Banana\n```\n\n(Type `I` to enter `--INSERT--` mode and `ESC` + `:wq` to write and quit the file when you're done).\n\n*This will open up again your editor with the following file content:*\n\n```txt\n# This is the 1st commit message:\n\nAdd Orange\n\n# This is the commit message #2:\n\nAdd Banana\n````\n\n*Change the file to this (and save it):*\n\n```txt\nAdd Orange and Banana\n````\n\n*Now, the log history will look like the following:*\n\n```txt\n$ git log --oneline --graph --decorate\n1eda1fa (HEAD -\u003e feature-one) Add Orange and Banana\n0285f89 (origin/master, origin/HEAD, master) First commit\n```\n\n*Merge the `feature-one` on branch master:*\n\n```txt\ngit checkout master\ngit merge feature-one\n```\n\n*Do the same rebasing on branch `feature-two`, and you will get the following:*\n\n```txt\n$ git log --oneline --graph --decorate\n1d1e743 (HEAD -\u003e feature-two) Add NodeJs and Java\n1eda1fa (HEAD -\u003e feature-one) Add Orange and Banana\n0285f89 (origin/master, origin/HEAD, master) First commit\n```\n\nThis strategy is really great if your feature branch is made up of a lot of commits.\nIn this case, you typically want to squash all your commits into one and merge it into the master branch.\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Favine%2Fgit-cheat-sheet","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Favine%2Fgit-cheat-sheet","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Favine%2Fgit-cheat-sheet/lists"}