kenichi

@kenichishibata

Git Push and Pull Tips and Tricks

push pull dance!

Pushing by default

Pushing to a remote by default pushes to a branch with the same name for example

if you are in dev branch

$ git checkout -b dev
Switched to a new branch 'dev'

And you have these remotes

$ git remote
codebase
origin

To see which remotes these are referring to you can add -v flag

Doing a push here will push to the remote with the same branch name

$ git push codebase
Total 0 (delta 0), reused 0 (delta 0)
remote:
remote: To create a merge request for dev, visit:
remote: https://codebase.your-gitlab.com/infra/cmp_configs_clone/merge_requests/new?merge_request%5Bsource_branch%5D=dev
remote:
To https://codebase.your-gitlab.com/infra/cmp_configs_clone.git
* [new branch] dev -> dev

As you see it pushes to a branch named dev as well on the remote side. If the branch does not exists on the remote side it will be automatically created.

If you are in dev branch locally and you try to push to another branch let's say master you will get this message without actual push

$ git branch
* dev
master
customer1/add-ext-js-packages
customer1/batch_somefunc
customer1/desktop-upgrade
customer1/shrink-somefunc/req/PROJECT-726
customer1/upgrade-and-add-elastic-desktop
customer2/local-auth
customer3/somelib-pipeline-fix
$ git push codebase master
Everything up-to-date

Setting up upstream

When you push you have the option to setup your upstream. Upstream in this context means your default remote tracking.

The syntax:

git push -u <remote> <branch>

Usually you want your branch name on local to be the same branch name on master

For example:

git push -u origin feat/new-feature-toggle

Once you setup your upstream you only need to do

git push

And it will automatically know which remote branch it refers to. Upstreams are done per branch.

To be able to check which upstream you are currently referring to run:

git branch -avv

Notice the two -v flag single -v will only give you the commit messages not including the upstream branch.

Pushing to a different branch

If you want to push to the same remote but a different branch. Use the following syntax;

git push <branch with new changes>:<branch you are pushing to>

For example:

git push origin dev:master

This pushses local dev branch to origin master branch

Pulling from a different branch

This is using the same syntax for pushing

git pull origin master:dev

This updates your local dev branch using the remote origin master branch

Push to a local branch

Check the branches both remote and local

$ git branch -av
* master
customer1/add-ext-js-packages
customer1/batch_somefunc
customer1/desktop-upgrade
customer1/shrink-somefunc/req/PROJECT-726

Push changes from master to -> customer1/add-ext-js-packages

$ git push --force . master:customer1/add-ext-js-packages
Total 0 (delta 0), reused 0 (delta 0)
To .
+ 3e205c3...31f2769 master -> customer1/add-ext-js-packages (forced update)

Notice the . where a remote should be. also branch to branch pushing is branch1:branch2

The syntax is :

git push . <branch with new changes>:<branch you are pushing to>

Similarly it is possible to pull from a local branch to another local branch

The syntax is

git checkout <branch you want updated>
git pull . <branch you want the updates>

Delete a remote branch by pushing

There is a lesser known fact that you can delete remote branches by pushing into them.

The syntax to delete these branches is.

git push origin :<branch>

For examples:

$ git branch -av
* dev
master
customer1/add-ext-js-packages
customer1/batch_somefunc
customer1/desktop-upgrade
customer1/shrink-somefunc/req/PROJECT-726
$ git push codebase :dev
Username for 'https://codebase.your-gitlab.com': kenichi.shibata
Password for 'https://kenichi.shibata@codebase.your-gitlab.com':
To https://codebase.your-gitlab.com/infra/cmp_configs_clone.git
- [deleted] dev
$ git branch -av
* dev
master
customer1/add-ext-js-packages
customer1/batch_somefunc
customer1/desktop-upgrade
customer1/shrink-somefunc/req/PROJECT-726

As you can see it deleted the dev branch on the remote side.

You can also push multiple at once

$ git push codebase :customer1/add-ext-js-packages :customer1/batch_somefunc  :customer1/shrink-somefunc/req/PROJECT-726
Counting objects: 14, done.
Delta compression using up to 56 threads.
Compressing objects: 100% (11/11), done.
Writing objects: 100% (14/14), 1.15 KiB | 0 bytes/s, done.
Total 14 (delta 8), reused 3 (delta 1)
remote:
remote: To create a merge request for customer1/upgrade-and-add-elastic-desktop, visit:
remote: https://codebase.your-gitlab.com/infra/cmp_configs_clone/merge_requests/new? merge_request%5Bsource_branch%5D=customer1%2Fupgrade-and-add-elastic-desktop
remote:
To https://codebase.your-gitlab.com/infra/cmp_configs_clone.git
- [deleted] customer1/add-ext-js-packages
- [deleted] customer1/batch_somefunc
- [deleted] customer1/shrink-somefunc/req/PROJECT-726

For other developers tracking this remote you have to ask them to pull or fetch --prune then do branch -d on your local machine to delete the local branch

Pushing a local COPY (not remote) of the repo

First create a local dir and do git init

$ mkdir test
$ cd test
$ ls
$ git init
Initialised empty Git repository in /home/shibata100012/company_workspace/cmp_core/cmp/test/.git/

Then go back to you repo and add the test directory as your remote (local)

$ git remote add local ../test
$ git remote -v
codebase https://codebase.your-gitlab.com/infra/cmp_configs_clone.git (fetch)
codebase https://codebase.your-gitlab.com/infra/cmp_configs_clone.git (push)
local ../test (fetch)
local ../test (push)
origin git@git.wsq.io:cmp_core/cmp_configs (fetch)
origin git@git.wsq.io:cmp_core/cmp_configs (push)

Finally do a push to that remote (local)

$ git push local
Counting objects: 14191, done.
Delta compression using up to 56 threads.
Compressing objects: 100% (5100/5100), done.
Writing objects: 100% (14191/14191), 1.41 MiB | 0 bytes/s, done.
Total 14191 (delta 6243), reused 14007 (delta 6097)
To ../test
* [new branch] dev -> dev

Pulling without merge commits

Most of the time when we do git pull if we have a the remote has a commit that we do not have locally git defaults to creating merge commits. Merge commits are commits which are seemingly empty and that they only adds the commit however in reality if you look closer and add -m flag while logging you can actually see that these commits do more sometimes. It can cause confusion if you are trying to track down a change that is in merge commit especially if you are merging commits manually.

My recommendation is to do away with merge commits and use rebase instead of merge.

Most developers uses this approach when rebasing a local clone against a remote.

$ git fetch <remotename>
$ git rebase <localbranch> <remotename>/<branch>

Most of the time it works well. However if you are writing tons of commits and have little patience fetching and rebasing manually you can do:

$ git pull --rebase

This will automatically do fetch and rebase instead of the default pull behaviour fetch and merge. Then you can resolve the conflicts if there is any.

Or if you are like me and you like shortcuts you can add it to your git aliases

[alias]
pullr = pull --rebase

Now you only have to do

git pullr

If you are looking for more convenient git aliases https://kenichishibata.net/my-gitconfig-with-all-the-bells-and-whistles-9479530f12af

More by kenichi

Topics of interest

More Related Stories