I have a development and production folder on the same server and 1 repo behind them to push to both folders depending on the branch that is pushed. I would like the development (test) folder to be deployed to when dev is pushed to the repo and the production folder (www) when master is pushed.
This works, but I have the problem of rewriting all files, not just those that have changed.
Example:
I am on local dev branch, make change only to file index.php, commit,
push - Changes are deployed do development folder, with only
index.php changed (new file timestamp).
Next step: git checkout master, git merge with dev branch and then
push to master - Changes are properly deployed to production folder,
but not only index.php is changed, but all files on FTP have new
timestamp.
Next step: git checkout dev, make some changes to fileX.php, commit and push to dev - Changes are properly deployed to dev folder, but again all files on FTP have new timestamp, not only fileX.php
Is it normal or am I doing something wrong? Maybe can you recommend a better git workflow if I have 1 local PC with git - 1 development domain and 1 production domain ?
Thanks for help
post-receive hook:
#!/bin/sh
while read oldrev newrev ref
do
branch=`echo $ref | cut -d/ -f3`
if [ "master" == "$branch" ]; then
git --work-tree=/home/www/domain.com/subdomains/www --git-dir=/home/www/domain.com/subdomains/repos/myrepo.git checkout master -f
echo 'changes pushed to production'
else
git --work-tree=/home/www/domain.com/subdomains/test--git-dir=/home/www/domain.com/subdomains/repos/myrepo.git checkout dev -f
echo 'changes pushed to dev'
fi
done
This post-receive hook is badly flawed. The good news is that it's easily fixed.
The root of your particular problem is that every Git repository, including the bare one1 that is receiving the push here, starts out with one (just one) index. The index keeps track of the (single, as in just one again) work-tree. This is true even though the whole point of a bare repository is to have no work-tree: it still has an index.
When one uses git --work-tree=<path> with this bare repository to do a git checkout operation, that checkout operation uses the (one, single) index to keep track of what it has stored in the (temporarily added) work-tree. That is, for the duration of the git checkout, this bare repository becomes non-bare: it has one index and one work-tree, and the work-tree is the one chosen for this one git checkout operation.
For each subsequent git --work-tree=<path> checkout operation, Git will assume that the index correctly describes the current checkout to the target work-tree. (Git may discover, as it does its work, that the index doesn't correctly describe the target work-tree, but it starts out assuming that it does.) The files that Git decides to update in that work-tree will be based on this assumption, with some corrections potentially, but not always, inserted as it goes. This main assumption, that the index correctly describes the current checkout to the work-tree, holds if and only if the path argument used in the subsequent git checkout is the same as the path argument used in the previous git checkout.
But we have two different git checkout commands:
git --work-tree=/home/www/domain.com/subdomains/www ...
and:
git --work-tree=/home/www/domain.com/subdomains/test
(small aside here: something went wrong with the cut-and-paste above as the --git-dir option is fused with the --work-tree; I have made my own assumption here about fixing it).
These are two different paths. They therefore need two different index files—or no index at all.2
1A bare repository is a Git repository where core.bare is set to true. A bare repository has no work-tree and its Git database files are stored in the top level, rather than under a separate .git directory.
2When there is no index, as in the initial git checkout, Git will build one as needed. This is more compute-intensive, and in a non-bare repository, where we actually use the index to build the next commit, destroying the index loses our carefully-built next commit: Git builds the new one from the current commit again so we have to start over.
The work-tree itself is not affected by this rebuilding process, but if we can afford the space for one index file per work-tree—and index files are generally pretty small—it seems likely that we should do that. Still, it's an option, if you want it.
Fixing the problem
First, although it's not really related, let's fix the other obvious (but minor) problem:
while read oldrev newrev ref
do
branch=`echo $ref | cut -d/ -f3`
Suppose we add a tag named master/v1.1. This ref has, as its full spelling, the name refs/tags/master/v1.1. Let's see what we get here:
$ ref=refs/tags/master/v1.1
$ branch=`echo $ref | cut -d/ -f3`
$ echo $branch
master
Whoops: our code will think we've updated branch master, when what we did is add the tag master/v1.1. We probably won't use such a tag, but why not do this correctly? Instead of using cut, let's check the whole reference:
case $ref in
refs/heads/*) branch=${ref#refs/heads/};;
*) continue;; # not a branch
esac
Trying this out with our test ref we get:
$ case $ref in
> refs/heads/*) branch=${ref#refs/heads/};;
> *) echo not a branch;;
> esac
not a branch
Replacing ref with refs/heads/master we get:
$ ref=refs/heads/master
$ case $ref in
refs/heads/*) branch=${ref#refs/heads/};;
*) echo not a branch;;
esac
$ echo $branch
master
(There's no PS2 output in this section because I used control-P to redo the previous case.)
For real correctness, we should also look at $old and $new to determine whether the ref in question is being created, updated, or deleted; but in this case we can just assume that branch names master and dev won't ever be deleted. So our new code reads:
#!/bin/sh
while read oldrev newrev ref
do
case $ref in
refs/heads/*) branch=${ref#refs/heads/};;
*) continue;; # not a branch - do not deploy
esac
case "$branch" in
master) wt=/home/www/domain.com/subdomains/www loc=production;;
dev) wt=home/www/domain.com/subdomains/test loc=dev;;
*) continue;; # not an INTERESTING branch - do not deploy
esac
# It's an interesting branch; deploy it to $wt. Use an index
# based on the branch name. There is no need to specify the
# git directory, which is in $GIT_DIR right now because this is
# a post-receive script.
GIT_INDEX_FILE=index.$branch git --work-tree=$wt checkout $branch -f
echo "deployed to $loc"
done
The -f option to git checkout here is somewhat dangerous: it will overwrite or remove files that got modified in the work-tree, even though we now have a proper index to keep track of which files should be in which state. But it was there before, so I've kept it.
This post-receive script (which I should note is entirely untested: watch out for typos) still has a flaw. Whatever branch we git checkout here, that will leave this repository set to recommend that branch to whoever clones this repository. Fixing this requires updating HEAD:
git symbolic-ref HEAD refs/heads/master
after the git checkout step. You have been living with this flaw all along, so maybe you don't really care about this one.
What I want to accomplish:
I have juts installed git on my development server.
I create a branch out of my 'develop' branch, work on my new feature branch, commit, and when I'm done - I merge the new feature branch with the 'develop' branch.
To apply the changes for the 'develop' branch on my development server I have to log in to my server and use git pull - which I'm trying to prevent and happen automatically - when there is something to pull from my development server - it will be done automatically.
I hope I'm clear about that I'm trying to accomplish ;)
What I have done up till now is:
Created a folder inside my project /www/hooks/ and added a file called post-merge: Following git documentation - this should get triggered whenever I merge a branch.
Inside this folder I added the text:
which should execute whatever is in between the backticks symbol ( ` ) as a shell command (following this PHP documentation)
Inside the folder /www/.git/hooks/ I added a symbolic-link to the file I previously mentioned with the same exact name: /www/hooks/post-merge :
sudo ln -s -f /www/hooks/post-merge /www/.git/hooks/post-merge
I gave the linked file under /www/.git/hooks/post-merge 775 file permission as the other files.
Some notes:
My repo is on Bitbucket
My directory /www/homepage/ is the one with the index file, so nothing can run outside of it on a browser (apache2 points to it..) - (but i guess there shouldn't be a problem since it's self executed via /.git/hooks ?)
I tried renaming both my files (the one under /www/.git/hooks/ & /www/hooks/) to post-merge.php and this didn't work.
just to have Carriage return
#!/bin/bash
git --git-dir "path/master/.git" --work-tree "path/master" pull origin master
you could try this in your post-merge
I am new in bitbucket.I want to upload project from Linux to bitbucket.successfully I have created a bitbucket account and did the following
1)create a repository name 'testadmin'
2)Using command line cd /var/www/myname/myprojectname
git init
git remote add origin https://username#bitbucket.org/user/testadmin.git
git pull origin master
then I get
Password for 'https://user#bitbucket.org':
From https://bitbucket.org/user/testadmin
* branch master -> FETCH_HEAD
Merge made by the 'recursive' strategy.
README.md | 29 +++++++++++++++++++++++++++++
1 file changed, 29 insertions(+)
But I didn't get my project from bitbucket.Please help me
ok, then
I would advice you to keep your project folder in www directly. Like if your project folder name is project_1 then it should be at var/www/html/project_1
then open terminal and reach to the folder project_1
cd /var/www/html/project_1 and then as you have already initiated git and added remote origin so you just need to push your code to repo.
To do so, follow these steps:
1) You need to add all the files to a commit bucket to upload on repo. For that,
git add -A (it will add all the files of the folder project_1)
2) Commit files with a message to track your uploaded work
git commit -m "First time uploading project 1" // The commit message will be for your reference.
3) Push the commited code now:
`git push origin master` // this command will push the code to master branch which is the default branch in a repo. You can create any branches on Bitbucket and add their name after origin to push to that particular branch.
After these 3 commands, check your repo. You should see your project up there.
Comment if you need further help.
I've been messing with this for like 2 days now and I'm not fully understanding the Git process yet and how I am supposed to deploy from github to production server.
Since it's a laravel website, what I did was first install a clean laravel installation on production, then added a git remote for the github repository. But when I try to do a git pull origin or git pull origin master, it keeps saying Already up-to-date.
Then I tried doing:
git checkout origin/master -b master2
But got the following error:
The following untracked working tree files would be overwritten by checkout:
_laravel/.env.example
_laravel/.gitattributes
_laravel/.gitignore
_laravel/app/Commands/Command.php
_laravel/app/Console/Commands/Inspire.php
_laravel/app/Console/Kernel.php
_laravel/app/Events/Event.php
_laravel/app/Exceptions/Handler.php
_laravel/app/Handlers/Commands/.gitkeep
_laravel/app/Handlers/Events/.gitkeep
_laravel/app/Http/Controllers/Controller.php
_laravel/app/Http/Controllers/WelcomeController.php
_laravel/app/Http/Kernel.php
_laravel/app/Http/Middleware/Authenticate.php
_laravel/app/Http/Middleware/RedirectIfAuthenticated.php
_laravel/app/Http/Middleware/VerifyCsrfToken.php
_laravel/app/Http/Requests/Request.php
_laravel/app/Http/routes.php
_laravel/app/Providers/AppServiceProvider.php
_laravel/app/Providers/BusServiceProvider.php
_laravel/app/Providers/ConfigServiceProvider.php
_laravel/app/Providers/EventServiceProvider.php
_laravel/app/Providers/RouteServiceProvider.php
So I guess I need to take everything from the repository and pull it to production server and force it to overwrite whatever is there now.
When you want to install an application on your server with git, you always start with making a clone of your repository into an empty folder. By adding a ., you can make a clone in your current directory. Otherwise, a new directory will be created.
You might decide to install your dependencies with composer on your production server. Then you make sure the vendormap is in your .gitignore. Then you can use composer install to load the dependencies, based on the composer-files you loaded with git.
i have some files and folder in my git repo. But some of them have a very long path that when i try to synchronize my workspace with git it gives me an error because windows cannot have characters in a path more than 260. Is there a way to pull specific files and folders? for example *.php files from /file/*.php?
I do not know much from git and also all other tutorials and answers i found here do not work. i even tried the git git_core.longpathenabled true but nothing happened.
Any ideas?
Is there a way to pull specific files and folders
Yes, you can use git filter-branch and or git subtree split
Sample code:
filter-branch
# Filter the master branch to your directory and remove empty commits
git filter-branch --prune-empty --subdirectory-filter YOUR_FOLDER_NAME filter_from_branch
This will checkout all your desired files from the given folder to the current directory
subtree split
git subtree split -P <name-of-folder> -b <name-of-new-branch>
If your repository is hosted on Github or similar, you can download the file individually over HTTP, but you obviously will not be able to push changes.
Finally, if your copy of the repo is located in a deeply-nested folder you could move it somewhere like Users\You\Projects\cloned.