One of the things that many tutorials and guides never teach you about
git is how to use it for your day-to-day work. Over time you learn what works and what doesn't, but it isn't always obvious and certainly isn't obvious how you should use it from the start.
So let's explore a possible typical workflow.
Using an existing repo
git clone some-repo.git - This is the usual starting point if you are aiming to work with an existing repo. You can append a directory name to the end which is where the repository will be cloned to. Some people also prefer to create a new directory, cd in to it, and run
git clone some-repo.git .
Creating a new repo
git init within the directory you wish to use for your repo will initialise it. You can have existing files within this directory. If you use this method, you will need to also add the files you want
git to keep track of, you can use the following methods:
- Add a
.gitignorefile to the root of the directory containing a list of files/types you do not want included. You can list explicit files and/or wildcard matches like
*.sowhich will exclude all files ending in
random*which will exclude anything with 'random' as the the first part of the file name. A
.gitignorewith a single
*wildcard in it will exclude everything.
git add .- This will add everything in the working directory, ideally you want to have the
.gitignoredone before doing this.
git add path/filename- Add a file explicitly. If you set up a
.gitignoreexclude everything then you will need to use
git add -f path/filenameto force tracking of that file.
git add -u- If you already have your files tracked with git, then using this command will add only updated/changed files.
- Note: You need to
git addany time you have modified files and are going to do a commit, generally
gitwill warn you when changes have been made which haven't been tracked.
If you intend to keep your newly created repo in a remote such as BitBucket or GitHub, go to those sites and create a repository using their interfaces, they will then give you a detailed set of commands to run to add the remote to your repo. Generally speaking it will follow this format;
git remote add origin git@git-repo-url/reponame.git- to add the remote as origin
git push -u origin master- to push everything upstream, assuming you've initialised and added files to your repo of course.
Before performing any work, and assuming you're working with a project which is being stored remotely, you should ideally
git pull to check upstream for changes before starting and ensure your local repo is up to date.
If you're working with someone else's project (or in a team) then it is always recommended that you work in a new branch to avoid contaminating the
git checkout -b newbranchname will create and checkout a new branch with the name specified by newbranchname, this is how you will perform the bulk of your work.
You can have multiple branches, for example you may have a branch of
dev_vector where you are writing new code for some vector calculations, and then you can have another branch from
documentation where you're adding docs to the source. You can also branch a branch and get messy via
git checkout -b new_vector dev_vector - this is a new branch off of
Now, do some work in that branch, and add your changes:
git add -uto add only updated files, and/or
git add files-explicitly, or wildcard
git add .which will add everything not blocked by
At this stage
git is tracking the changes you've made, but they haven't actually been added to the repo proper, essentially you've just prepared
git for a commit; so either
git committo commit the files, this will then pop-up a commit message in your preferred text editor where you should ideally describe what changes have been made (as a whole)
git commit -m"Your message here" if you want to do a quick commit without adding a fancy message.
A small note on commit messages
Commit messages are an important guide to you when looking at the history of a project, and a well written commit message is invaluable. We've all been guilty of writing such gems as "asdasdasd" (much like how we probably mashed the keyboard for a game save name at least once), and when trying to find a breaking change, this is just plain unhelpful. Rather than extoll the virtues of commit messages here, please read this excellent post by Chris Beams.
Now! If you're working with a repo that is tracked upstream (I really hope you are, or at least keep regular backups), run
git push. This is optional, you can just keep it all local if you want, and sometimes this is the case when you're just experimenting with code in a random branch. You can of course just keep the
master branch upstream, and keep all your branches local.
In the case that you are working on someone elses, or an organizations project, please do follow their guidelines for commits if they have a guide.
Merge to the Master branch
Assuming you've made all your changes and committed them to the hallows of
git, you're now in a position to get them in to the
master branch which is where the main code is developed.
The first thing you should do is make sure
master is up to date, so quickly do;
git checkout master
Now checkout back to your working branch,
git checkout branchname. You should then
git rebase master your changes on the current
master, this is the fun part. What this does is rewinds your changes back to the point where you branched, then replays your changes on to the
master from the point where you branched off. If things go smoothly, then there won't be anything for you to do apart from
git add -u and
git commit, before the next step.
If for some reason you had issues then
git will tell you all about it. Likely you will need to edit the problem files where
git will have inserted lines which include the lines to be changed, and the changes.
So now that your branch is updated to the current
master, it's time to actually merge your changes.
git checkout master
git merge branchname
Since we prepared by first getting the branch updated to
master, this should have been completely pain free (this is why we update the branch first). So go ahead and perform the holy trinity;
git add -u
Notes: Some extra little helpful tidbits
Instead of doing lots of small commits and pushes, you can amend the last commit and add to it with
git commit --amend. For example, you forgot to rename something, or added a new file, rather than adding yet another commit, just amend the last one. But be aware, don't make this your primary mode of committing code and be sure to create a regular commit - the last
--amend you do will be the last full commit before the next.
To simplify the above,
git commit --amend will append changes to the last commit, a
git commit is a new commit.
If you really screwed up with your changes, you can run
git reset --hard or
git reset --hard *some commit*, this will take your current branch back to the last commit or commit specified and change all staged (git add) files back to that point. Use with caution!
You can checkout a commit, run
git log to see a list of commits, and then
git checkout *change-hash* where change-hash looks similar to
commit 917854a9760fc662b341efe1c0b51671535ab423 under
Want to know what changed between commits? Run
git log to view the history, then run
git diff 14b8..b410 where 14b8..b410 is the first few characters of the commits you want to compare. Order matters! so if you compare
most-recent..least-recent then you will get changes listed in reverse order to the actual commit timeline. To view changes in timeline order you will need to compare least-recent to most-recent.
You can also run
git diff path/to/filename to see only what has changed with that file, likewise you can also use
git log path/to/file to see its history.
There is also
git log -p path/to/filename, this will give you a change log which also contains a diff between each change. This and the above commands can be used to compare branches as well.