I'm currently working from two different computers on a project - a laptop running Linux, and a desktop running Win7. I'm using an ubuntu server with gitolite on it to host my repos.
I'm trying to write a quick script that will do two things :
Check if anything has changed on the local repo, since the last push. If so, it should commit changes, push the commit to the remote repo
1a. I'm not sure how this works, but I DONT want this commit to overwrite changes in files that I haven't changed locally (ie: they may have been changed on the other computer, and pushed)
After that, it should check if the remote repo has any files that have been changed since my last pull (see 1a.). If so, pull those changes into the local repo.
The intention of this script is to keep both computers synced with each other, without having to manually do all of this git work each time. I would like to have this run periodically (once every half hour?), so I don't want it to take a huge amount of resources, if possible.
I don't need the whole script written for me (unless it is just a couple lines) - just point me towards the commands I will need.
Compare the output of:
git ls-remote <remote>
git show-ref
Although generally what is done is to fetch (not pull) the remote and compare the remote branches with your local branches. If you have non-fast forward merges, you can't really automate because manual intervention on the merge will be required before pushing again.
Related
Pretty new to Git - been using TFS and simple commit/push/branching, so any help appreciated - have spent all day reading and running tests and beginning to think my requirement may not be possible.
There are two of us in the office; Dev 1 doing mostly compiled C# server code, and Dev 2 mostly exclusively web page related work. However, as there are only two of us we do need to cross over fairly regularly, particularly with client Javascript functionality.
We've been doing the "mate I'm working on foo.js" method of source control for client side code, and its worked for a while, but we are doing bigger projects and it's becoming a liability.
Our set up is as below, all on an internal network:
Dev 1's machine
Dev 2's machine
Local Windows Server running IIS that serves the websites under development
Shared drive pointing to the IIS root
So, and this is the rapid development cycle I'd like to try and keep, Dev 2 browses to the site under development edits the script / css / html files on the shared drive, hits F5, and the updates are immediately visible. This is a huge benefit for fast working with client side code.
The problems usually occur when Dev 1 needs to make a change to some scripted functionality that happens to require a style change, the same files are opened and saved by both devs, and one of the change sets is lost.
So I'd like to prevent this! However as far as I understand, Git requires the devs to have local repositories so changes can be done without affecting anyone else at all, and then conflicts are merged on commit?
I have set up a test repository on the local server and tried a few scenarios, but as I kind of expected, the scenario where both devs save the same open file is not tracked because neither set of changes has been committed, so as before, only the last set of changes is visible anywhere.
Is there any way of having these type of changes to the same physical file tracked? Or if not, a setup that does track them properly but at least maintains a rapid workflow as close as possible to the above?
Use branches.
Git has a very good branch system. Just create a branch for the work you do - you can even create a branch for every feature you want to implement. And when you "finished" the implementation, merge the branch back to master. So both - and more - developers can work based on a working master version and add there code to the common codebase if it works.
So, the workflow could look like this:
Dev1 and Dev2 clone the repo: git clone ....
Dev1 works on feature A: git checkout -b A (this creates a lokal branch A)
Dev2 works on feature B: git checkout -b B
Dev2 finishes his work: git push (on the first call you get a error message about the upstream, the errormessage contains exactly the line you need to create correct upstream, just copy it)
git checkout master; git pull back to master branch and pull
git merge B this merges B into master
Dev1 need longer for the job and wants to update to newest codebase:
git checkout master; git pull; git checkout A; git merge master branch A of Dev1 is now on new codebase.
If you have to work on different features at the same time, there exists also a good system in git. Based from master branch, create a new branch in its own folder - so that both branches are checked out at the same time and there is no need to git checkout <branch> to switch between them:
git worktree add -b <branch> <path>, like git worktree add -b A ../A
now you can switch to it trough filesystem (cd ../A) and work on both (or others you created the same way)
If you use github or gitlab, you can protect the master branch and create rules to make merges into it (called pull requests). With appveyor, travis-ci and others there exists services where you can let unittests run and give the pull request free it the unittests do not fail. Based on such a workflow, every developer can work on a running codebase.
About conflicts: With the workflow up there they do not happen as long as both versions didn't modify the same line. But you get a message at the (local) merge, and in the files it is good explained what you can do:
(we create a file with a b c in each line, in master we edit b to e, in our branch A we edit b to d, we commit both and merge master into A)
a
<<<<<<< HEAD
d
=======
e
>>>>>>> master
c
Ideally, you would:
isolate the common files in one separate Git repository
separate source control (the remote Git repository) from deployment (files copied on IIS root)
That way, each of you can:
push to a common remote bare repository: configure it to deny any non-fast-forward push. In case of concurrent pushes, you will be forced to pull first, resolve any conflict locally, then push back: there won't be any change overridden or lost that way.
setup a server-side hook in order to (on the server) pull from said bare repository, through a post-receive hook (example here).
reference that common repository in your own development repo through a Git submodule.
The goal is to keep separate:
project-specific development from common client Javascript functionality.
versionning from deployment.
The problems usually occur when Dev 1 needs to make a change to some scripted functionality that happens to require a style change, the same files are opened and saved by both devs, and one of the change sets is lost.
…
Is there any way of having these type of changes to the same physical file tracked?
To get this you need some sort of collaborative editor, that's out-of-scope for any existing vcs I know of.
Or if not, a setup that does track them properly but at least maintains a rapid workflow as close as possible to the above?
You need separate files, separate saves (i.e. a vcs) and a workflow that automates as much as possible of the pull-and-push publishing loop.
Since you're not working on the same physical files, before publishing you need to sync your changes with whatever the other guy(s) on your team have published since last you looked. Decide how you want your final history to look; for small-team work like this rebasing onto a shared linear history is often a great place to start, so git config pull.rebase true. Then when you're ready to publish the changes you've saved, commit, pull, push is your cycle; if you and your buddy are making changes even in the same file it'll still apply cleanly in one go so long as the changes aren't immediately-adjacent or overlapping.
Say a user initiated a git pull on a big, big repo on a remote Windows server. It'll take several minutes to complete. I, another user altogether, remote into the same machine and navigate to that same folder. How can I tell if the other user's git pull is complete?
For context, this folder clones a remote repo to make files available for sharing from it like a CDN. I'm not interested in sharing the machine with another programmer as part of my workflow. I want to know if our file-share has finished updating.
Git is a distributed source control system. The intended use here is for you to git clone the repo on your local machine and work from it. As you finish pieces of work, you can git push to the server. Using a central repo where each developer works on a local one is very common with git. I suggest you do some research on different workflows that are used.
This might be verbose, but I'm just starting out with git, so I'm still learning here.
Before now, I've had a team of developers all working off of the same hard drive with a local copy of all of our dev files. So we have 1 hard disk and 4 developers. All of us use sublime text and work on the projects together. We all work in the same room, so it's never been an issue to work on the same project at the same time. We just don't work on the same file at the same time. Not the greatest system, but it worked at the time.
Now we want to introduce git to the team for all of the reasons a VCS is important. The problem we're running into is files being locked by one user and no one else can use git on that repository.
Here's an example. I log into my mac in the morning and make some changes to files in Project X located at /Volumes/dev/projectx/. I open terminal and commit those changes to the local repository (stored also at /Volumes/dev/projectx/). My coworker gets in and logs into his mac. He opens up his terminal to check the status on the repo he's working on. So he moves into /Volumes/dev/projectx/ and runs git status. He gets an error message that says the index is locked. In order to allow him to run any git commands on the repo, I have to completely log out (maybe just kill some processes, but I don't know which ones). After I log out, he can work as though there's no problem.
Is there any way that we can both work on the same local repository at the same time?
I've also discovered that, if I'm working in a project that has a git repository in it and anyone else even opens the project folder in a finder window, it completely locks me out from using that git repo (same index lock error).
We're willing to change the way we work on files, but since there are literally thousands of projects on the drive, it isn't really practical for each of us to have our own local copies of all of the files. Also, since many of the changes are a very simple text change of some kind, it seems tedious to host all of these repositories remotely and have to pull down all the files anytime we only want to update a single file.
I'm really looking for workflow suggestions here, but the question I asked is kind of the starting point here.
The whole point of using git is that you don't have to do this kind of crazy stuff.
I know what you've said about why you don't think you should all have complete copies. Here's the hard truth. You're wrong. Mostly. But that's ok, you said your willing to rethink how you work and that's good. Ill try to explain why its not that big a deal to have everyone use their own clones.
A assume all code is already in a remote repository - if its not, sign up on http://github.com or http://bitbucket.com and get a free repository, add it as a remote to your git repo, and push it up. Its really very simple.
Each of your developers should then make their own directory locally on their machines where they can clone the whole repository.
git clone http://github.com/yuoraccount/yourrepo ~/clones/localproject
The first time they clone, it will take a little time to download everything, but from then on, only each minor diff will need to be downloaded uploaded. Git is made to be efficient that way.
When you make a change, commit it, and push it up.
git commit -am "i made a small change"
git push origin master
Then everyone can pull it down.
git pull origin master
You can even all work on different branches, so your not just pushing to the same branch. This should all be really simple, and very easy to do.
You can also split your project into multiple repositories, but you don't really need to. Thousands of files is not a big deal, git can handle it without a problem. That's not to say that you won't have some challenges. Git is easy to use, but you'll eventually run into merge conflicts. They will be a little bit frustrating at first, but stack overflow has a thousand answers explaining how to deal with them - you should be fine.
This is what git is for.
Git is a decentralized version control system. The way you want to use git could be described as the opposite of decentralized.
There are a number of perfectly reasonable workflows possible with git, but all of them are going to involve each developer working in a local clone of some repo.
i guess that your "single harddisk" is really a single "network storage" that can be accessed concurrently. otherwise i don't see the problem (the harddisk can only be attached to a single computer at any time; whenever you unplug the disk, any locks should be released!)
anyhow, though you currently consider it impractical, you still might consider using per-user clones of the repositories.
the normal workflow of a multi-user repository would consist of a local clone of each repository on each developer machine (that is: a clone on your personal mac).
then the trouble with concurrently accessing the locked central repository doesn't exist!
it's exactly the use-case for which git was designed.
this would allow your users to work on the repository even without having access to your central network storage.
if you are concerned about disk-space, you might be happy to hear that git does a pretty decent job of compressing the data (just run git gc every once in a while in your repository).
if (for whatever reasons) you cannot have local copies (on the dev-machine) of the repositories, you might consider having per-user clones on the central storage.
git can use hardlinks for local clones, so disk-space should not be an issue here.
Section 4 of the Pro Git book (version 2) is about "Git on the Server" and gives some information about what the OP is trying to achieve.
The OP's situation calls for the "Local Protocol".
Here is how this works:
1. Create a local remote from your project
cd into your project and create the remote in your preferred location (in your example /Volumes/dev/projectx):
git remote add origin /Volumes/dev/projectx.git
2. Set the permissions for the remote
git init --bare --shared /Volumes/dev/projectx.git
This will set the permissions properly so that different users can push and pull to/from the remote. This command does not affect your Git history and is safe to run.
The --bare flag is used because all that is needed for a remote is a bare repository, that is, a repository without a working directory (a repository with only the .git directory and nothing else).
Note: this step is not described in the Git Book for the Local Remote protocol and is only suggested when setting up a Git server, but in the experience of a colleague, without using this step, the permissions were not set properly.
3. Push the data to your new remote
Assuming you have a branch called main (do this for any branch you want your collaborators to have access to):
git push --set-upstream origin main
4. Have your collaborators clone the remote
This works as with any remote:
git clone /Volumes/dev/projectx.git
From here on, everybody can push and pull to/from the local remote.
I'm trying to get a feel for how to do certain things in TortoiseGit that are pretty intuitive in TortoiseHG.
TortoiseHG has the Workbench which basically is my central tool to sync the local repository with remote ones: upstreams and origin.
It is easy to see what changes I'm missing locally (so I need to fetch them) or remotely (so I need to push them).
What is similar functionality in TortoiseGit?
How can I see a list of changes from a remote origin or upstream that I want to fetch locally?
How can I see a list of changes locally that want to push to the origin or upstream?
Maybe TortoiseGit does not have those; if not: please suggest tools that do.
My answer doesn't directly apply to TortoiseGit, but im sure you will find the equivalent features easily.
Git is a distributed version control system. In order to see the remotes changes, you need to fetch them first:
git fetch
Then you can use git diff to view the differences between your current branch, or even your current (dirty) working directory.
Alternatively you may use git merge --dry-run to see what has to be merged.
To see the things you have changed but not commited (uncommited changes) just type git status.
SourceTree can do this: without the need to fetching, it shows I'm 1 change behind on the upstream remote.
After pulling it, it shows the origin remote is 2 changes behind on master.
Switching to GitHub and can't seem to find information on how to do something I used to do with SVN:
First of al I'm a tester so I never commit changes, but I do need to keep a number of local copies of the project each with a small difference to trunk - staging, production, decreased timer values etc
I used to use CornerStone on Mac (just fwiw/don't have it any more), and a single update from SVN would update all my various local 'dependent projects' (all of them the same, apart from one or two lines, usually in a config file). I'd review the inevitable conflicts and almost always reject them, provided the only difference in the conflicting file was my customisation for test purposes, or if there was something new I'd merge it in and leave my staging environment URLs or whatever as they were.
Can I do this sort of thing efficiently with GitHub? (preferably using GitHub's/Xcode's or some other Mac GUI client?)
I did look at the documentation, but can't seem to find anything on this so any help much appreciated/maybe it's kind of unusual to be pulling changes to lots of almost-identical local projects and always be rejecting certain conflicts.. :)
Of course, the ideal solution is to not have configuration data tracked in the repository, or at least make it possible to override via some untracked file.
However, there's no problem with what you want to do in git. You just locally make multiple clones of your GitHub repository. In each, you can make your changes specific to that local copy, and then commit them. Then, when you want to update from the latest version of GitHub, make sure that you pull with:
git pull --rebase
... which will fetch the latest version from the server, and then try to reapply your commits with local changes on top of them. Unless the same parts of the files that you've committed changes to have also been modified in the new commits on GitHub, you shouldn't even have conflicts to resolve.
If you always pull like this, then the commit graph (history) of your project will always be the same as the remote, but with any of your local changes as the most recent commits on top of the remote history.
(I would hope that the GUI clients that you are using have an option to rebase on pulling new changes. Otherwise you can set this to happen automatically with the config option branch.<name>.rebase, where <name> is the name of your local branch.)