First of all, you should really not develop on the server. Unless you have a very complicated server, I think you should be able to set up a local "server".
This is not that hard to do, either using:
- your local machine as server,
- a virtual machine (VM) (see e.g. Vagrant),
- a container (see Docker).
The advantage of a VM or container is that this can be ported more easily to other developers or when you change computers. Also, if you have multiple projects with different technologies, this avoid having multiple (conflicting?) servers running on your machine all the time.
Now on to the actual question. There are a few options that I see.
The easiest solution was already suggested in the comments:
- just write a script to
scp
/rsync
/... over your files to your server. This doesn't take longer than running a git push
and the script is probably just a single line.
If you really want to use git push
for this, I would recommend the following:
- make sure your server acts as a git server and set up a hook for
post-receive
. The latter could be a script that just checks out the current master
branch to your public_html
directory or something like that.
There are quite a bit of more advanced options, e.g.
- if you already have a Continuous Integration (CI) server such as Jenkins, there are plugins that help to publish your website after passing all tests (by running a script, copying the files, ...). So this is obviously the more robust choice, but setting up Jenkins can be daunting at first (there are other providers of CI software, though).
I am a user of SVN and now I am learning GIT.
Welcome to the gang!
SVN Re-education
In SVN I usually [...]
Hold on for a moment. While CVS and SVN and other traditional (i.e. centralized) version control system fulfill (mostly) the same purpose as modern (i.e. distributed) version control systems like mercurial and Git, you'll be much better off learning Git from the ground up instead of trying to transfer your SVN workflow to Git.
http://hginit.com (view on archive.org) by Joel Spolsky (one of the very founders of Stack Exchange) is a tutorial for mercurial, not Git, but it's zero-th chapter, "Subversion Re-education" is useful for people switching away from SVN to any distributed version control system, as it tells you what SVN concepts you have to (temporarily) un-learn (or to stash
away, as Git users might say) to be able wrap your head around the distributed version control system concepts and the idiomatic workflows established to work with them.
So you can read that zero-th chapter and mostly just replace the word "mercurial" with "Git" and thereby properly prepare yourself and your mind for Git.
The fine print
(You might skip this for now.) While mercurial and Git are much more similar to each other than to SVN, there are some conceptual differences between them, so some of the statements and advice in "Subversion Re-education" will become technically wrong when replacing "mercurial" with "Git":
- While mercurial internally tracks and stores changesets, Git internally tracks and stores revisions (i.e. states of the content of a directory tree), just like Subversion does. But other than Subversion Git performs merges by looking at the differences between each involved branch respectively and a common ancestor revision (a true 3-point-merge), so the result is much the same as for mercurial: Merging is much easier and less error-prone than in SVN.
- While you can branch in Git by cloning the repository (as is customary in mercurial), it's much more common to create a new branch within a Git repository. (That's because Git branches are simply (moving) pointers to revisions, whereas mercurial branches are permanent labels applied to every revision. These permanent labels are usually unwanted, so mercurial workflows usually work by cloning the complete repository for diverging development.)
In SVN, everything is a directory (but you shouldn't necessarily treat it as such)
But I've been interrupting you. You were saying?
In SVN I usually checkout on my local machine a repo, which includes all branches in my project and I used to select the folder for my branch I am interested to and work there.
If, by that, you mean you've checked out the SVN repository's root folder (or any other folder corresponding to more than to trunk
or to a single branch, e.g. in the conventional SVN repo layout the branches
folder containing all non-trunk branches) then I dare say you've probably used SVN wrong(ish), or at least abused a bit the fact that trunk, branches and tags are all folded into a single (though hierarchical) namespace together with directories within the revisions/codebase.
While it might be tempting to change several SVN branches in parallel, that is AFAIK not how SVN is intended to be used. (Though I'm unsure about what specific downsides working like that might have.)
In Git, only directories are directories
Every clone of a Git repository is itself a Git repository: By default, it gets a full copy of the origin repository's history, including all revisions, branches and tags. But it will keep all that our of your way: Git stores it in a file-based database of sorts, located in the repository's root folder's hidden .git/
subfolder.
But what are the non-hidden files you see in the repository folder?
When you git clone
a repository, Git does several things. Roughly:
- It creates the target folder, and in it, the
.git/
subfolder with the "database"
- It transfers the references (tags, branches etc.) of the origin repository's database and makes a copy of them in the new database, giving them a slighly modified name that marks them as "remote" references.
- It transfers all the revisions (i.e. file tree states) that these references point to, as well all revisions that these revisions point to directly or transitively (their parents and ancestors) to the new database and stores them, so that the new remote references actually point to something that's available in the new repository.
- It creates a local branch tracking the remote revision corresponding to the origin repository's default branch (usually
master
).
- It checks out that local branch.
That last step means that Git looks up the revision that this branch points at, and unpacks the file-tree stored there (the database uses some means of compression and de-duplication) into the repository's root folder. That root folder and all its subfolders (excluding the special .git
subfolder) are known as your repository's "working copy". That's where you interact with the content of the currently checked-out revision/branch. They're just normal folders and files. However, to interact with the repository per-se (the "database" of revisions and references) you use git
commands.
Seeing Git branches and interacting with Git branches
Currently I am cloning a repo and clone a specific branch using gitk.
The version of gitk
I got cannot clone repositories. It can only view repo history and create branches and check out branches. Also, there's no "cloning" a branch. You can only clone repositories.
Did you mean you clone a repo using git clone ...
and then, using gitk
, check out a branch?
The project folder contains only the content for that branch and I cannot see all branches as in SVN, which is a little confusing for me.
[...]
- I would like to know if the git process I described is "standard" and some how correct [...]
Yes, that is pretty standard:
- Clone a repository using
git clone ...
- Check out the branch you want to work on with
git checkout ...
or using a graphical tool like gikt
I cannot find an easy way to see all branches in my local repository using GIT.
- [...] or I am missing smt.
Maybe:
How to work with multiple branches in parallel
- Also I would like to know how to handle a process where I need to work on two branches at the same time in case, for example, I need to make an hotfix on master but keep the content of another branch too.
There's different scenarios here:
A new (yet to be created) change needs to be applied to multiple branches
Use this workflow:
- Create a new branch
c
from a revision that already is in the ancestry of all these branches (e.g. the revision that introduced the bug when the change will be a bugfix) or from a revision that (including all its ancestors) is acceptable to be introduced in all these branches.
- Make and commit the change on that new branch
c
.
For each branch b
that needs the change:
Check out b
:
git checkout b
Merge c
into b
:
git merge c
Remove branch c
:
git branch --delete c
An existing change is needed on a different branch
(... but without the other changes made on the where that change resides)
- Check out the branch where the change is needed
- Cherry-pick the revision(s) making the change, in order
On one branch a
, you want to change one or some files to the exact state they have on a different branch b
- Check out
a
Get the file contents from branch b
:
git checkout b -- path/to/a/file.txt path/to/another/file.cpp or/even/a/complete/directory/ ...
(Other than git checkout
without passing paths, this won't switch to branch b
, only get the requested file contents from there. These files might or might not already exist on a
. If they do, they're overwritten with their content on b
.)
While working on one branch, you want to look at how things are on another branch
Check out the branch you want to work on.
Then, for looking at the other branch,
- either use graphical tools that allow you to view the contents of not currently checked out revisions (e.g. in
gitk
try to switch the radio buttons from "patch" to "tree")
- or clone the repository to a temporary directory and check out the other branch there
- or use
git worktree
to create a separate working directory of the same repository (i.e. also using the database in .git/
directory of your current local repository) where you can check out that other branch
Best Answer
As a cautionary note up-front, the way that git works means that if the solution is stored in the same repository as the project definition and if students are expected to clone that repository to get a copy of the project definition, then the students will also get a copy of the solution in their clone. This means that if a student is a little git-savvy, they will have access to the solution before they attempted the exercise themselves. If that is undesired, then you should keep the solution in a separate repository (for example, as if you were a student who has done the work in a previous year already).
In git, tags and branches are both just named labels to a particular commit. The main difference is that a branch-type label can easily be moved to a different commit and that typically happens automatically when a new commit is added to a branch. tag-type labels can only be moved to a new commit manually.
If it is very rare that corrections need to be made to the solution, then you could adopt a workflow where you make the correction at the milestone where it is needed and then rebase the rest of the milestones on top of the corrected version and re-apply the milestone tags to the new commits.
If it is not that rare that corrections need to be made, it might be better to maintain a branch per milestone and to apply the correction to each of them (possibly by cherry-picking the relevant commits).
Both of them require a fair bit of manual work where errors can be made, but the use of branches is easier to grasp for most people and that makes it easier to correct any errors that were made in the process.