.. -*- coding: utf-8 -*- .. role:: sref(numref) .. role:: xref(numref) .. Copyright (C) 2014,2020, Wolfgang Scherer, .. This file is part of Documentation Standard. .. Permission is granted to copy, distribute and/or modify this document .. under the terms of the GNU Free Documentation License, Version 1.3 .. or any later version published by the Free Software Foundation; .. with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts. .. A copy of the license is included in the section entitled "GNU .. Free Documentation License". .. inline comments (with du_comment_role) .. role:: rem(comment) .. role:: html(raw) :format: html .. role:: shx(code) :language: sh .. rst-class:: xnarrow xmedium large xhuge xultra ################################################## :rem:`|||:sec:|||`\ VCS - Git ################################################## .. >>CODD See `the components of a doctoral dissertation and their order `_ .. >>CODD Dedication .. >>CODD Epigraph .. >>CODD Abstract .. compound:: .. \|:here:| .. >>CODD Introduction .. >>CODD Chapter ================================================== :rem:`|||:sec:|||`\ GUI ================================================== The standard GUI for git(1) is: .. code-block:: sh gitk gitk --all The commit tool is: .. code-block:: sh git gui Other programs: :cola: The highly caffeinated Git GUI :qgit: QT interface to git trees, with stgit support. :gitg: Git repository viewer ================================================== :rem:`|||:sec:|||`\ github fork ================================================== After `cloning a github fork`_ and `adding an upstream repository`_, everday repeating operation is `syncing the github fork with upstream`_. -------------------------------------------------------- :rem:`||:sec:||`\ Syncing the github fork with upstream -------------------------------------------------------- #. Clean up: .. code-block:: sh git stash git checkout master # -f #. Update upstream: .. code-block:: sh git fetch upstream #. Merge upstream: .. code-block:: sh git merge upstream/master #. Get current work: .. code-block:: sh git stash pop / apply git stash clear # if anything left on stash -------------------------------------------------- :rem:`||:sec:||`\ Cloning a github fork -------------------------------------------------- .. code-block:: sh git clone git@github.com:wolfmanx/REPOSITORY.git -------------------------------------------------- :rem:`||:sec:||`\ Adding an upstream repository -------------------------------------------------- .. code-block:: sh git remote add upstream https://github.com/ORIGINAL_OWNER/ORIGINAL_REPOSITORY.git Example: .. code-block:: text sheckley:.../3rd-party/w2ui/w2ui$ git remote -v origin git@github.com:wolfmanx/w2ui.git (fetch) origin git@github.com:wolfmanx/w2ui.git (push) upstream https://github.com/vitmalina/w2ui.git (fetch) upstream https://github.com/vitmalina/w2ui.git (push) ================================================== :rem:`|||:sec:|||`\ Quickstart ================================================== See status: .. code-block:: sh git status Get updated info from remote repositories: .. code-block:: sh git fetch --all Get and merge remote into local: .. code-block:: sh git pull Show branches: .. code-block:: sh git branch git branch -a Update remote refs along with associated objects: .. code-block:: sh git push Show remotes: .. code-block:: sh git remote -v Go to specific commit (revision): .. code-block:: sh git checkout revision Fix # HEAD detached at 1.7.1: .. code-block:: sh git checkout master -f If you want to revert changes made to your working copy, do this: .. code-block:: sh git checkout . -f If you want to revert changes made to the index (i.e., that you have added), do this: .. code-block:: sh git reset If you want to revert a change that you have committed, do this: .. code-block:: sh git revert ... Abort a merge: .. code-block:: sh git reset --hard HEAD Remove changes: .. code-block:: sh git branch git reset --hard HEAD Create/apply patches: .. code-block:: sh git format-patch deadbeef..b00b5 # => 001-title.patch, 002-title.patch, ... git format-patch master.. # everything on a branch git format-patch master...branch # from merge point git am *.patch # separate commits # if there are problems git am --continue git am --skip git am --abort git apply *.patch # no commit, single patch ================================================== :rem:`|||:sec:|||`\ Tricks ================================================== ---------------------------------------------------------- :rem:`||:sec:||`\ Find the first commit of a branch ---------------------------------------------------------- .. code-block:: sh git log master..branch --oneline | tail -1 E.g.: .. code-block:: sh git log master..i18n-default-locale --oneline | tail -1 # 40f5c99 option i18n.notrans for language alias of C locale git diff 40f5c99~1 i18n-default-locale >tg2-i18n-notrans.patch ---------------------------------------------------------- :rem:`||:sec:||`\ Delete commits ---------------------------------------------------------- .. w3m -dump https://stackoverflow.com/questions/1338728/delete-commits-from-a-branch-in-git See `git rebase - Delete commits from a branch in Git - Stack Overflow`_ Assuming you are sitting on that commit, then this command will wack it... .. code-block:: sh git reset --hard HEAD~1 The HEAD~1 means the commit before head. Or, you could look at the output of git log, find the commit id of the commit you want to back up to, and then do this: .. code-block:: sh git reset --hard ---- If you already pushed it, you will need to do a force push to get rid of it... .. code-block:: sh git push origin HEAD --force However, if others may have pulled it, then you would be better off starting a new branch. Because when they pull, it will just merge it into their work, and you will get it pushed back up again. If you already pushed, it may be better to use git revert, to create a "mirror image" commit that will undo the changes. However, both commits will be in the log. ---- FYI -- :samp:`git reset --hard HEAD` is great if you want to get rid of WORK IN PROGRESS. It will reset you back to the most recent commit, and erase all the changes in your working tree and index. ---- Lastly, if you need to find a commit that you "deleted", it is typically present in git reflog unless you have garbage collected your repository. .. _`git rebase - Delete commits from a branch in Git - Stack Overflow`: https://stackoverflow.com/questions/1338728/delete-commits-from-a-branch-in-git ---------------------------------------------------------- :rem:`||:sec:||`\ How to modify existing, unpushed commits ---------------------------------------------------------- Best answer on `Stack Overflow`_ is: `git - How to modify existing, unpushed commits?`_: Question: I wrote the wrong thing in a commit message. Alternatively, I've forgotten to include some files. How can I change the commit message/files? The commit has not been pushed yet. ---- **Amending the most recent commit message** .. code-block:: sh git commit --amend will open your editor, allowing you to change the commit message of the most recent commit. Additionally, you can set the commit message directly in the command line with: .. code-block:: sh git commit --amend -m "New commit message" However, this can make multi-line commit messages or small corrections more cumbersome to enter. Make sure you don't have any working copy changes staged before doing this or they will get committed too. (Unstaged changes will not get committed.) **Changing the message of a commit that you've already pushed to your remote branch** If you've already pushed your commit up to your remote branch, then you'll need to force push the commit with: .. code-block:: sh git push --force # Or git push -f Warning: force-pushing will overwrite the remote branch with the state of your local one. If there are commits on the remote branch that you don't have in your local branch, you will lose those commits. Warning: be cautious about amending commits that you have already shared with other people. Amending commits essentially rewrites them to have different SHA IDs, which poses a problem if other people have copies of the old commit that you've rewritten. Anyone who has a copy of the old commit will need to synchronize their work with your newly re-written commit, which can sometimes be difficult, so make sure you coordinate with others when attempting to rewrite shared commit history, or just avoid rewriting shared commits altogether. ---- **Use interactive rebase** Another option is to use interactive rebase. This allows you to edit any message you want to update even if it's not the latest message. In order to do a git squash, follow these steps: .. code-block:: sh # X is the number of commits to the last commit you want to be able to edit git rebase -i HEAD~X Once you squash your commits - choose the e/r for editing the message **Important note about Interactive rebase** When you use the git rebase -i HEAD~X there can be more than X commits. Git will "collect" all the commits in the last X commits and if there was a merge somewhere in between that range you will see all the commits as well so the outcome will be X+. Good tip: If you have to do it for more than a single branch and you might face conflicts when amending the content set up the `git rerere`_ and let git resolve those conflicts automatically for you. .. _`git rerere`: https://stackoverflow.com/questions/35415925/is-it-possible-to-setup-git-merge-for-automatic-resolving-git-rerere/35417944#35417944 .. `powershell - Is it possible to setup git merge for automatic resolving? (git rerere)`_ .. _`powershell - Is it possible to setup git merge for automatic resolving? (git rerere)`: https://stackoverflow.com/questions/35415925/is-it-possible-to-setup-git-merge-for-automatic-resolving-git-rerere/35417944#35417944 .. _`Stack Overflow`: https://stackoverflow.com .. _`git - How to modify existing, unpushed commits?`: https://stackoverflow.com/questions/179123/how-to-modify-existing-unpushed-commits ================================================== :rem:`|||:sec:|||`\ Create branches ================================================== Branching allows you to build new features or test out ideas without putting your main project at risk. In git, branch is a sort of bookmark that references the last commit made in the branch. This makes branches very small and easy to work with. How do I use branches? Branches are pretty easy to work with and will save you a lot of headaches, especially when working with multiple people. To create a branch and begin working in it, run these commands: .. code-block:: sh git branch mybranch # Creates a new branch called "mybranch" git checkout mybranch # Makes "mybranch" the active branch Alternatively, you can use the shortcut: .. code-block:: sh git checkout -b mybranch # Creates a new branch called "mybranch" and makes it the active branch Create a branch tracking a remote branch, if it was created remotely: .. code-block:: sh git checkout -b serverfix origin/serverfix Or push it, when ready: .. code-block:: sh git push Where is typically origin, the name which git gives to the remote you cloned from. Note however that formally, the format is: .. code-block:: sh git push : To switch between branches, use git checkout: .. code-block:: sh git checkout master # Makes "master" the active branch git checkout mybranch # Makes "mybranch" the active branch Once you're finished working on your branch and are ready to combine it back into the master branch, use merge: .. code-block:: sh git checkout master # Makes "master" the active branch git merge mybranch # Merges the commits from "mybranch" into "master" git branch -d mybranch # Deletes the "mybranch" branch Tip: When you switch between branches, the files that you work on (the "working copy") are updated to reflect the changes in the new branch. If you have changes you have not committed, git will ensure you do not lose them. Git is also very careful during merges and pulls to ensure you don't lose any changes. When in doubt, commit early and commit often. ================================================== :rem:`|||:sec:|||`\ Patches ================================================== See `Create a git patch from the changes in the current working directory - Stack Overflow`_: .. code-block:: sh git format-patch master..my-branch .. _`Create a git patch from the changes in the current working directory - Stack Overflow`: https://stackoverflow.com/questions/5159185/create-a-git-patch-from-the-changes-in-the-current-working-directory/52314638#52314638 .. w3m -dump https://stackoverflow.com/questions/2249852/how-to-apply-a-patch-generated-with-git-format-patch See `How to apply a patch generated with git format-patch? - Stack Overflow`_ Note: You can first preview what your patch will do: First the stats: .. code-block:: sh git apply --stat a_file.patch Then a dry run to detect errors: .. code-block:: sh git apply --check a_file.patch | Finally, you can use `git am`_ to apply your patch as a commit: it allows you to sign off an applied patch. | This can be useful for later reference. .. code-block:: sh git am --signoff < a_file.patch .. _`git am`: https://git-scm.com/docs/git-am .. _`How to apply a patch generated with git format-patch? - Stack Overflow`: https://stackoverflow.com/questions/2249852/how-to-apply-a-patch-generated-with-git-format-patch ================================================== :rem:`|||:sec:|||`\ Github Forking ================================================== -------------------------------------------------- :rem:`||:sec:||`\ Step 3: Configure remotes -------------------------------------------------- When a repository is cloned, it has a default remote called origin that points to your fork on GitHub, not the original repository it was forked from. To keep track of the original repository, you need to add another remote named upstream: .. code-block:: sh cd Spoon-Knife # Changes the active directory in the prompt to the newly cloned "Spoon-Knife" directory git remote add upstream https://github.com/octocat/Spoon-Knife.git # Assigns the original repository to a remote called "upstream" git fetch upstream # Pulls in changes not present in your local repository, without modifying your files More Things You Can Do You've successfully forked a repository, but get a load of these other cool things you can do: Push commits Once you've made some commits to a forked repository and want to push it to your forked project, you do it the same way you would with a regular repository: .. code-block:: sh git push origin master # Pushes commits to your remote repository stored on GitHub Pull in upstream changes If the original repository you forked your project from gets updated, you can add those updates to your fork by running the following code: .. code-block:: sh git fetch upstream # Fetches any new changes from the original repository git merge upstream/master # Merges any changes fetched into your working files What is the difference between fetch and pull? There are two ways to get commits from a remote repository or branch: git fetch and git pull. While they might seem similar at first, there are distinct differences you should consider. Pull: .. code-block:: sh git pull upstream master # Pulls commits from 'upstream' and stores them in the local repository When you use git pull, git tries to automatically do your work for you. It is context sensitive, so git will merge any pulled commits into the branch you are currently working in. One thing to keep in mind is that git pull automatically merges the commits without letting you review them first. If you don't closely manage your branches you may run into frequent conflicts. Fetch & Merge: .. code-block:: sh git fetch upstream # Fetches any new commits from the original repository git merge upstream/master # Merges any fetched commits into your working files When you git fetch, git retrieves any commits from the target remote that you do not have and stores them in your local repository. However, it does not merge them with your current branch. This is particularly useful if you need to keep your repository up to date but are working on something that might break if you update your files. To integrate the commits into your local branch, you use git merge. This combines the specified branches and prompts you if there are any conflicts. ================================================================= :rem:`|||:sec:|||`\ Resolving merge conflicts with git and kdiff3 ================================================================= From http://jeroen.haegebaert.com/post/2008/08/26/Resolving-merge-conflicts-with-git-and-kdiff3 To fix the conflicts using kdiff3, first you need to tweak the kdiff3 configuration a bit: start kdiff3, and go to Settings, Configure KDiff3, Integration. Under 'Command line options to ignore', add '--' separated by a ';' if necessary. To resolve conflicts, you can now use: .. code-block:: sh git mergetool -t kdiff3 To permanently configure kdiff3 as the merge tool (so you don't need to specify the '-t kdiff3' anymore): .. code-block:: sh git config merge.tool kdiff3 .. >>CODD Conclusion .. >>CODD Appendix A .. \|:here:| .. >>CODD Notes .. ================================================== .. :rem:`|||:sec:|||`\ Footnotes .. ================================================== :html:`
` .. \[#] .. \|:info:| put local references here .. \|:info:| put local definitions here .. include:: doc_defs.inc .. include:: abbrev_defs.inc .. include:: doc_defs_combined.inc .. .. \||<-snap->|| doc_standalone .. include:: doc/doc_defs_secret.inc .. \||<-snap->|| doc_standalone .. \||<-snap->|| not_doc_standalone .. include:: doc_defs_secret.inc .. \||<-snap->|| not_doc_standalone .. _`Wolfgang Scherer`: wolfgang.scherer@gmx.de