Git is a version control system.
Git helps you keep track of code changes.
Git is used to collaborate on code.
Version control systems like git
emerged from the problem of how to let a lot of people work on one code base at once, without ever losing anybody's work or breaking the project etc.
There are two ways to interact with git
-- either using a command line terminal (including the one built into the VS Code editor), or using a visual app (like the Github app). I strongly recommend learning to use the command line version, partly because it works everywhere, and partly because sometimes the the Github app gets stuck and you have to go to the command line to fix it anyway.
The basic idea:
Remember, Git and Github are different things.
First, check whether you already have it, by typing this into your terminal console and pressing 'enter':
git --version
If you get a message back saying that the git
command can't be found, you need to install Git. Follow the instructions here: https://git-scm.com/book/en/v2/Getting-Started-Installing-Git
Before using git you need to configure it with your name & email, so that your code changes are properly identified:
git config --global user.name "your name here"
git config --global user.email "your@email.here"
First, you need the appropriate address of the repo to clone. On Github this can be found in the green "Code" dropdown button on the main page.
E.g. our project's Github URL is: https://github.com/worldmaking/2024-datt4520-digm5520
The Git URL for this repo is: https://github.com/worldmaking/2024-datt4520-digm5520.git (notice that it ends with .git
)
Then, make sure that you are in the right parent folder in your console/terminal, and then:
git clone --recursive https://github.com/worldmaking/2024-datt4520-digm5520.git
This will create a local copy of the "main" branch of the repo, which you can now work on locally, making edits as needed.
At this point the usual workflow is to:
git add filename
for each new filegit status
to verify the list of what has changedgit commit -am "description of change"
to add this to your historygit pull
to pull in the latest changes from the remote repository, and handle any conflicts if they happengit push
to push your changes to the remote repositoryIf you edited a file that was already tracked in the repo, it will already be staged. You can verify this with
git status
If this command lists any untracked files that should be part of the repo, you need to add them:
git add myfilename
Again you can git status
to verify this has worked.
Now you can commit the change to your local history. A commit requires a descriptive message, typically just a few words, to say what changed:
git commit -a -m "I fixed problem X"
Or just
git commit -am "I fixed problem X"
The -a
part means commit everything staged. The -m
part means "here is the message describing this change".
Now the changes are part of your history, and you have just created a new version.
Do not add large files to git repos: Git is only designed for working with small files, like simple text files. Large media assets should never be in a git repo. We have to find a different solution for managing these if we need them.
DO not add temporary or system files: Things like _DS_Store files or other normally-hidden files, or temporary files, or locally-generated files (like node_modules
) should not be part of the repo. We can tell git to ignore certain paths and file types using the .gitignore
file. For example, our project's .gitignore
file currently contains things like the following -- any file with these pathname patterns will be ignored by git:
logs
*.log
node_modules/
.env
temp/
.temp
.cache
After committing, the next thing we need to do is make sure we are up to date with the remote repo, because maybe somebody else has been pushing changes since you last did this. Always pull the latest changes before you push your own.
Get the latest changes with:
git pull
At this point, usually everything goes well and you get the message that you are up to date
. This is the point where git combines your changes with all the other changes that have happened to the repo since you last pulled it.
However, there is a chance that at this point you get a conflict -- which means that your changes cannot be combined with somebody else's changes without losing work. So at this point git will ask you to resolve the conflict before you can do anything else. Follow the instructions that it gives you to do this.
Once any conflicts are resolved, we can then push our changes to the remote repo like this:
git push
Branches are a way to store a parallel version history, which we can merge back later if we wish to.
There are two common cases where we want to use branches:
We want to make sure that the branch we are working on during development is not the same branch that is currently the live server (or the version that people will get when they download the repo).
We want to create a temporary branch to work on a specific "feature" in isolation from other development. This is called a feature-branch workflow.
Here are the important commands
List all branches:
git branch -a
Switch to a different branch:
git checkout thebranchname
git pull
git checkout develop
git pull
git checkout main
git pull
When you do this, you'll see all your local files on disk change to match the state of the branch on the repo.
Now you can make changes on this branch, and use git status
, git add
and git commit
to add and commit files as normal. These commits go to the branch you are now working in. And you can push these changes to the remote branch using git push
.
This is typically what you need to do a feature-branch. First you need a simple name for the branch, e.g. "feature_mything"
git checkout -b feature_mything
Now you can use git status
, git add
and git commit
to add and commit files as normal, and the commits will go to your local "feature_mything" branch.
If you want to push this work onto the remote repo, so that others can see your new branch, or just to make sure it is stored in the cloud, you can git push
it. However the first time you do this, git doesn't yet know where to push it to, because it is a new branch. So the first time you push your branch, you need to set it up to also create a branch on the remote origin repo. You can do it like this:
git push -u origin feature_mything
From this point on, the relationship between your local and remote "feature_mything" branches is set up, and now you can just use git push
.
Let's say your "feature_mything" branch was branched from the "develop" branch. You've worked on the "feature_mything" branch for a while and you are happy that the feature is working and ready to merge back into the "develop" branch. Here's what you need to do.
Make sure all your changes are committed (use git status
to verify)
Switch to the receiving branch ("develop") and make sure it is up to date:
git checkout
git pull
If it is all up do date, now you can merge in your feature branch:
git merge feature_mything
If any conflicts arise these need to be resolved immediately.
Otherwise, your merge is now complete. You can now git push
the develop branch.
If you are finished with the feature branch, you can delete the local branch like this:
git branch -d feature_mything
To delete a remote branch:
git push origin -d feature_mything
There's a neat feature of Github that allows the easy creation of a public client-side website.
All you have to do is create and work on a branch with the special name gh-pages, then any files that you commit here will be the content of a static website. The URL of this website depends on the github owner account and the repo name:
https://ownername.github.io/reponame
For example, these course notes are actually hosted via a Github project. The project is at https://github.com/worldmaking/digm5520. The URL of the pages is https://worldmaking.github.io/digm5520.
However as our project this year has its own web server we don't need to use the github pages feature for the live project pages, but we may perhaps use this feature to document the project.
Another way to collaborate via git is to create a Fork. You can do this on Github for any public project. A Fork is a copy of a repo that has the same history but is no longer connected to it. But after making changes to a Fork, you can submit a "Pull Request" to whoever manages the original repo, and they can review your changes before pulling them into their own repo.
Conflicts can happen sometimes when collaborating on code, where different people can create edits that git
can't merge by itself. In these cases, git status
will tell you you have unmerged paths
After committing your change, and then running a git pull
, you get a message saying there is a conflict in a file ("both modified").
Open that file in a text editor (e.g. VS Code). Search the file for the text <<<<<<
to see where each conflict begins.
Conflicts are marked in the text file like this:
unchanged content
<<<<<<< HEAD
your changes
=======
the other person's changes
>>>>>>> branch-a
unchanged content
Edit the file manually to the point that it should be, removing the <<<<<<< HEAD
, =======
and >>>>>>> branch-a
accordingly.
Do this for every conflict in every file that had conflicts.
Verify that your edits are correct and the code is working properly.
Only after verifying this, add your changes using
git add .
And commit with a message, e.g.
git commit -m "Resolve merge conflict by incorporating both suggestions"
It would be a good idea to git pull
again to ensure the conflicts are done, and git push
if you are collaborating on a remote branch so that other collaborators get your work too.
Here git status
will give you a message "deleted by" for each file in question.
Open the file to have a look at the latest changes, and verify whether the file should be kept or deleted.
To delete it, use git rm filename
. To keep it, use git add filename
.
Once you have run either git rm filename
or git add filename
, and you have resolved all other conflicts, you can then commit the changes:
git commit -m "Resolve merge conflict by incorporating both suggestions"
It would be a good idea to git pull
again to ensure the conflicts are done, and git push
if you are collaborating on a remote branch so that other collaborators get your work too.