diff --git a/autoload/magit/git.vim b/autoload/magit/git.vim
index 9c48939d01cc5eec16b03d3b5c1253ff103a30db..54efe7811b9d655d1eb95b44523c886e085d4fb0 100644
--- a/autoload/magit/git.vim
+++ b/autoload/magit/git.vim
@@ -1,4 +1,5 @@
-let s:git_cmd="GIT_CONFIG=/dev/null GIT_CONFIG_NOSYSTEM=1 XDG_CONFIG_HOME=/ git"
+let s:git_cmd="GIT_CONFIG=/dev/null GIT_CONFIG_NOSYSTEM=1 git"
+
 
 function! magit#git#get_version()
 	if ( !exists("s:git_version") )
@@ -268,6 +269,70 @@ function! magit#git#git_unapply(header, selection, mode)
 	endif
 endfunction
 
+" magit#git#submodule_status: return the submodule status output
 function! magit#git#submodule_status()
 	return system(s:git_cmd . " submodule status")
 endfunction
+
+" magit#git#current_branch: return the current branch name, HEAD if not on a
+" branch
+function! magit#git#current_branch()
+	return magit#utils#strip(magit#utils#system(s:git_cmd .
+				\ " rev-parse --abbrev-ref HEAD"))
+endfunction
+
+" magit#git#last_commit: return the summary of the last commit of the current
+" branch
+function! magit#git#last_commit()
+	return magit#utils#strip(magit#utils#system(s:git_cmd .
+				\ " show -s --oneline"))
+endfunction
+
+" magit#git#default_remote: return the default remote name of the current
+" branch
+function! magit#git#default_remote(branch)
+	let git_cmd = s:git_cmd .
+		\ " for-each-ref --format='%(push:short)' refs/heads/" . a:branch
+	let remote = magit#utils#strip(magit#utils#system(git_cmd))
+	"WRONG! local branch can be different than remote branch!
+	let remote = remote[:-(strlen(a:branch)+2)]
+	if ( index(remote, b:remote_names) == -1 )
+		echoerr 'Magit internal error in magit#git#default_remote, please report a bug'
+	endif
+	return remote
+endfunction
+
+" magit#git#refresh_remote_list: update the buffer variable b:remote_names
+" with remote names
+function! magit#git#refresh_remote_list()
+	let b:remote_names = magit#utils#systemlist(s:git_cmd . " remote")
+endfunction
+
+" magit#git#remote_comp: completion function for remote names
+function! magit#git#remote_comp(lead,cmd,pos)
+	return filter(copy(b:remote_names), 'v:val =~ "^' .a:lead. '"'  )
+endfunction
+
+" magit#git#remote_branch_comp: completion function for remote branch names
+function! magit#git#remote_branch_comp(lead,cmd,pos)
+	let remote_name = b:cur_push_remote . "/"
+	let remote_branches = magit#utils#systemlist(s:git_cmd .
+		\ " for-each-ref --format='%(refname:short)' refs/remotes/" .
+		\ remote_name)
+	let len=strlen(remote_name)
+	call map(remote_branches, 'v:val[' . len . ':]')
+	call filter(remote_branches, 'v:val =~ "^' .a:lead. '"'  )
+	return remote_branches
+endfunction
+
+" magit#git#push
+function! magit#git#push(remote, branch)
+	silent let git_result=magit#utils#system(
+		\ s:git_cmd . " push " . a:remote . " " . a:branch )
+	if ( v:shell_error != 0 )
+		echoerr "Git push error: " . git_result
+	endif
+endfunction
+
+" remote.pushdefault and branch.<name>.pushremote since 1.8.3
+" @{push} since 2.5.0
diff --git a/plugin/magit.vim b/plugin/magit.vim
index edc2bc6c4ec81ad2e1513d1681edb5d9bc7d7571..6d2ee49ed59a20e07bd6195bff2ab81806d0307f 100644
--- a/plugin/magit.vim
+++ b/plugin/magit.vim
@@ -28,6 +28,7 @@ let g:magit_commit_mapping         = get(g:, 'magit_commit_mapping',
 let g:magit_commit_amend_mapping   = get(g:, 'magit_commit_amend_mapping',      'CA' )
 let g:magit_commit_fixup_mapping   = get(g:, 'magit_commit_fixup_mapping',      'CF' )
 let g:magit_close_commit_mapping   = get(g:, 'magit_close_commit_mapping',      'CU' )
+let g:magit_push_mapping           = get(g:, 'magit_push_mapping',              'gp' )
 let g:magit_reload_mapping         = get(g:, 'magit_reload_mapping',            'R' )
 let g:magit_ignore_mapping         = get(g:, 'magit_ignore_mapping',            'I' )
 let g:magit_close_mapping          = get(g:, 'magit_close_mapping',             'q' )
@@ -677,6 +678,7 @@ function! magit#show_magit(display, ...)
 	execute "nnoremap <buffer> <silent> " . g:magit_commit_amend_mapping . " :call magit#commit_command('CA')<cr>"
 	execute "nnoremap <buffer> <silent> " . g:magit_commit_fixup_mapping . " :call magit#commit_command('CF')<cr>"
 	execute "nnoremap <buffer> <silent> " . g:magit_close_commit_mapping . " :call magit#close_commit()<cr>"
+	execute "nnoremap <buffer> <silent> " . g:magit_push_mapping .         " :call magit#push()<cr>"
 	execute "nnoremap <buffer> <silent> " . g:magit_ignore_mapping .       " :call magit#ignore_file()<cr>"
 	execute "nnoremap <buffer> <silent> " . g:magit_close_mapping .        " :call magit#close_magit()<cr>"
 	execute "nnoremap <buffer> <silent> " . g:magit_toggle_help_mapping .  " :call magit#toggle_help()<cr>"
@@ -1006,6 +1008,27 @@ function! magit#jump_hunk(dir)
 	endif
 endfunction
 
+function! magit#push()
+	call magit#git#refresh_remote_list()
+	let cur_branch = magit#git#current_branch()
+	let remote = input("Remote: ", magit#git#default_remote(cur_branch), 'customlist,magit#git#remote_comp')
+	if ( index(b:remote_names, remote) == -1 )
+		echohl WarningMsg
+		echom "Remote '" . remote . "' do not exists"
+		echohl None
+		return
+	endif
+	try
+		" beurk, dirty way to pass a parameter to a customlist function
+		let b:cur_push_remote = remote
+		let branch = input("Branch: ", cur_branch, 'customlist,magit#git#remote_branch_comp')
+	finally
+		let b:cur_push_remote = ""
+	endtry
+	call magit#git#push(remote, branch)
+	echom "Pushed on " . remote . "/" . branch
+endfunction
+
 command! Magit call magit#show_magit('v')
 command! MagitOnly call magit#show_magit('c')