push all except an special branch

3k Views Asked by At

I and my teammate are working on the same project on OpenShift. we have several branches which have to be on the server, so we use command push --all, each of us (I and my teammate) want to have a local branch (called LocalTest) for our local tests and develop so the problem is when we use push --all origin branches are made for all of the branches which include LocalTest.

by the way, I forgot to point that, sometimes we need to merge other branches to our local one especially after pulling their new commits from the server and also want to cherry pick or even merge (rarely) from our local branch to other branches which will be push to server.

is there any command in git like git push --all except branch-name and what is the best solution for our problem?

4

There are 4 best solutions below

4
On

One solution would be to have a dedicated local clone in which you have only LocalTest.

You would make your push --all from your current local clone, where you have all your branches.

sometimes we want to merge other branches (specially their new commtis) to our local branch so there isn't good idea for dedicated local clone

It is a good idea: you can add your first clone as a remote of your second clone (which has the local test branch).
That means you can fetch at any time any branch from the first clone, and merge them to the LocalTest branch.


Alternatively, You could try and prevent one branch to be pushed (with a pre-push hook, but that would fail the all push --all, which is not practical.

0
On

git push --all except master would also be a good beginning

The problem is: the refspec pattern is quite limited.

The refspec documentation is clear:

You can’t use partial globs in the pattern, so this would be invalid:

fetch = +refs/heads/qa*:refs/remotes/origin/qa*

However, you can use namespaces (or directories) to accomplish something like that.
If you have a QA team that pushes a series of branches, and you want to get the master branch and any of the QA team’s branches but nothing else, you can use a config section like this:

[remote "origin"]
    url = https://github.com/schacon/simplegit-progit
    fetch = +refs/heads/master:refs/remotes/origin/master
    fetch = +refs/heads/qa/*:refs/remotes/origin/qa/*

If you have a complex workflow process that has a QA team pushing branches, developers pushing branches, and integration teams pushing and collaborating on remote branches, you can namespace them easily this way.

This approach applies to git push as well, with remote.<name>.push entries.

That way, a default git push would only push the desired refspecs... provided the excluded branch(es) is/are in a separate namespace.

And this is still a white list approach: you have to list the branches you want to push, for each namespace, and leave out the one namespace you do not want.


Working example:

cd /path/to/repos
git init example
echo test>afile
git add .
git commit -m "First commit in master"
git checkout -b private/abranch
echo abranch>>afile
git add .
git commit -m "First commit in a private branch"
git checkout master

cd ..
git init --bare example.git
cd example
git remote add origin ../example.git

git config remote.origin.push refs/heads/master:refs/remotes/origin/master
2
On

Simplest for this is going to be setting push.default to matching.

Any branches you want pushed, give them the same names as the matching branches on the upstream repo. Any branches you don't want pushed, give them names that don't exist there. Then your push is just a bare git push.

If you want to work on an local-only version of an upstream branch, just give it a name that doesn't match, e.g. git checkout -b local/master origin/master

0
On

You may always make up your own way which works best for you. You can use this one-liner in git bash.

git push origin $(echo "$(git branch)" | sed 's/*//' | sed 's/<excluded_branch_name>//')

For example, I use this command when I want to push everything except the master branch.

git push origin $(echo "$(git branch)" | sed 's/*//' | sed 's/master//')

You may add as many piped sed command applications as you need. $(... | sed 's/<your_branch_name>// ...).

The command works in the following way:

git branch lists all the local branches including master and a "*" character next to the current branch. echo outputs the output again. first sed removes the * char and then I use sed to replace other branch names with empty strings. The output of the command will be the list of all branches except those removed. This is passed as an argument to git push origin with the aid of the $(...) syntax.