diff --git a/Git-Quickstart.md b/Git-Quickstart.md index 0ce2aa9..9db0dde 100644 --- a/Git-Quickstart.md +++ b/Git-Quickstart.md @@ -1,84 +1,172 @@ +### Overview + Quick and dirty git contributing to a random project -``` -# fork the project to your personal space on the webUI - +- `origin` is the accepted name for you / your forks +- `upstream` is the accepted name for master projects +- "pull request" (PR) and "merge request" (MR) are two terms for the same technical thing in the webUIs: + - Github/Gitea use PR + - GitLab uses MR -# pull down your working copy from your fork, then connect it to the project -# - "origin" is the accepted name for you / your forks -# - "upstream" is the accepted name for master projects -git clone git@:/.git +"Master" and "Main" are two words which refer to the same thing, logically. Whether your upstream repo uses "Master" or "Main" just depends on that repo's details. + +Big picture of what's being done: + +1. Copy ("fork") the project ("upstream") to your private space ("origin") where you have edit capability +2. Make a feature branch from this copy ("origin") to make your contributions +3. Request your changes be merged to the project ("upstream") from your fork +4. Re-sync your origin fork of (1) after (3) is accepted +5. Remove your origin branch (2) now that it's integrated to upstream (1) + +How the upstram projects maintains it's working code varies project by project; some maintainers just use the Master/Main branch only, some use a secondary branch typically named "devel" - there are two conceptual ways to do source control, each project has it's own way of doing things. Look for a document `CONTRIBUTING.md` in the repo for instructions if it exists. + +The below examples use the source control method where Master/Main is never edited directly; a secondary branch named "devel" exists upstream which we branch from and PR/MR against; upstream maintainers then merge devel -> master on their timeframe to make official releases. Not everyone does it this way, learn how the upstream project wants you to do it and follow their instructions for details. + +In many cases, `git` assumes you mean `origin` when it's not directly specified on the commandline; for example `git checkout devel` is shorthand for `git checkout origin/devel`; this is used below to reduce typing fatigue, however you can always use the name of the remote in every command if you like and it helps learning. You must always name the remote if it is not `origin`, such as `git fetch upstream/devel` for example to indicate you want that specific upstream remote code, not origin. + + +### Process + +Fork the `upstream` project to your personal space on the webUI to create `origin`; this is done via clickable links in Github, Gitea, GitLab, etc. There is typically a button in the menubar of the webUI, it varies by software but the idea is the same for all of them - copy their stuff to your space so you can edit. + +Pull down (`clone`) your working copy from your fork (`origin`), then connect it to the `upstream` project - these are known as "remotes" in git terminology: + +``` +git clone git@:/.git cd git remote add upstream git@:/.git +``` -# configure your working fork, required for commits +Configure your working clone of `origin`, name/email are required for commits in git: + +``` git config user.name git config user.email +``` -# switch to the project working branch where you base changes off of -# - you connect it to *your* working copy of the branch, *not* upstream -# - track it for changes, will be used when syncing your fork later +Switch to the project working branch where you base changes off of: + +- you connect it to *your* working copy of the branch, *not* upstream +- track it for changes, will be used when re-syncing your fork later + +``` git checkout --track origin/devel +``` -# now make your new branch to edit code n stuff -# - defaults to branching from current point, origin/devel in this example -# - different source point can be named, just add to end of command +Now make your new branch to edit code in prep for submitting back upstream: + +- defaults to branching from current point, `origin/devel` in this example +- different source point can be named, just add to end of the command + +If you were to imagine what the below does visually, it sort of looks like this in tree form (hence "branch"): + +- `origin/master` + - `origin/devel` + - `origin/mynewbranch` + +``` git checkout -b +``` - +Edit all the things you need to edit - that might be adding new files, changing existing ones, whatever the case may be. The rule of thumb is to try and keep all changes grouped in logical commits; if you need to due 2 things which are not really related, commit the work as 2 unique commits for example with nice comments. There is a bit of an art to this you will learn over time. -# commit your local edits to your local working copy +Commit your local edits to your local working copy: + +``` git add file/name.py CHANGELOG.md ... git commit -m "my fix" file/name.py CHANGELOG.md ... +``` -# push your new working branch to your fork -# - -u tracks it, in case you have to make more fixes +Push your new working branch to your fork: + +- `-u` tracks it, in case you have to make more fixes + +``` git push origin -u +``` -# use the website to create a PR and wait for feedback etc. - - +Use the website to create a PR/MR and wait for feedback etc. This varies by software on the exact details, but there is usually a clickable button on *your* fork which says "Prepare Pull Request" or "Create Merge Request", where you then pick "from" and "to" to the maintainers: -## IF REQUIRED make fixes and re-push them, this is why we tracked it above -git commit -m "oopsie daisy" file/name.py +- "from" is your `origin/mynewbranch` +- "to" is upstream's branch that you started from (`upstream/devel` e.g.) -## IF REQUIRED squash your mistake cause it's just a typo nobody cares +Wait for feedback on changes needed to your work, or for your changes to be accepted and merged. Let's assume you receive feedback to fix a typo or whatever. -# get list of commits and find the one BEFORE your above commit +Make fixes and re-push them, this is why we tracked it above: + +``` +git commit -m "typo fix" file/name.py +``` + +SOME projects do not like to see little typo fixes, and request that you "squash" the fixups back into one single commit; this is up to the upstream maintainers how they want to run their project, some people like to see every typo fix as a unique commit - it just depends. + +IF REQUIRED squash your fixups back into one single commit and "force-push" it back to your origin; the webUI magically updates itself when the last step is done, so you can check your work by reloading the PR/MR web page: + +``` +# get list of commits and find the one BEFORE your above commit and get ID (big hex string) git log -# rebase your work on that commit ID from the log + +# "rebase" your work on that commit ID from the log git rebase -i + +# an editor window (vim, etc.) appears: # change 'pick' on first line to 'reword' # change every following line to 'fixup' # save-quit, update new commit message -# force-push your squashed changed hashes overtop your PR -# - this automagically updates on the webUI in realtime + git push origin -f +``` - +Your work is now accepted/merged by upstream. Your last two tasks - assuming you want to keep contributing to this project - are to: -## sync your fork and delete your now useless branch from your fork -## - it's two steps - first done to working copy, then pushed to your fork +1. Re-synchronize your `origin` copy with the `upstream` merges, then +2. Delete your feature branch from `origin` and push the delete back to your private space -# switch to the working branch the project uses that you branched off of +This part can be confusing, think of your workstation as a proxy - you pull the changes from upstream to your workstation, merge them locally, then push them to origin to update your copy in the webUI. + +Switch to the working branch the project uses that you branched off of: + +``` git checkout devel +``` -# get the latest upstream code (stashes it locally) +Get the latest upstream code (stashes it locally but does not apply yet): + +``` git fetch upstream -# apply the stashed updates to your working copy -git merge upstream/devel -# push your working copy to your fork, it's now in sync again -git push origin devel +``` -## IF REQUIRED - delete your branch from working copy, push delete to your fork -## - notice the colon in front of the name of the branch in step 2 +Apply the stashed updates to your working copy: + +``` +git merge upstream/devel +``` + +Push your working copy to your fork, it's now in sync again: + +``` +git push origin devel +``` + +Delete your branch from working copy, push delete to your fork + +- notice the colon in front of the name of the branch, this is a git-ism for "delete" or "deleted file": + +This process step should be "clean" - git is smart, it recognizes from the above steps that the code you worked on has been merged by upstream. If that did *not* happen, then when you attempt to run the first command below it might issue a warning or error "there are commits still on this branch not merged" (sic - the message varies) to try and help you. + +Sometimes you just perform these two steps to throw away a bad branch, the warnings/errors do not always mean it's not a correct action for your needs. We will assume that the changes were accepted and merged here and no warnings/errors: + +``` git branch -d git push origin : +``` -## if upstream adds a brand new branch after you forked and you want to -## integrate it into your workflow +This last step is a bonus - sometimes upstream adds *new* branches after you've forked; if you want to grab those new branches from upstream and add them to your origin, then: + +``` git fetch upstream git checkout -b upstream/ git push origin -u ``` +This is not generally necessary unless you want that new branch for some special reason.