choose your own adventure – git fixes
https://sethrobertson.github.io/GitFixUm/fixup.html
remove local commits
git checkout master // Make sure you are on correct branch (If not doesn't work) git reset --hard origin/master // Reset local changes to origin/
git remote -v
If you have more than one remote, the command lists them all.
git remote -v
Pushing to Your Remotes
When you have your project at a point that you want to share, you have to push it upstream. The command for this is simple: git push
$ git push origin master
This command works only if you cloned from a server to which you have write access and if nobody has pushed in the meantime. If you and someone else clone at the same time and they push upstream and then you push upstream, your push will rightly be rejected. You’ll have to fetch their work first and incorporate it into yours before you’ll be allowed to push. See Git Branching for more detailed information on how to push to remote servers.
Inspecting a Remote
If you want to see more information about a particular remote, you can use the git remote show
$ git remote show origin * remote origin Fetch URL: https://github.com/schacon/ticgit Push URL: https://github.com/schacon/ticgit HEAD branch: master Remote branches: master tracked dev-branch tracked Local branch configured for 'git pull': master merges with remote master Local ref configured for 'git push': master pushes to master (up to date)
It lists the URL for the remote repository as well as the tracking branch information. The command helpfully tells you that if you’re on the master branch and you run git pull, it will automatically merge the remote’s master branch into the local one after it has been fetched. It also lists all the remote references it has pulled down.
That is a simple example you’re likely to encounter. When you’re using Git more heavily, however, you may see much more information from git remote show:
$ git remote show origin * remote origin URL: https://github.com/my-org/complex-project Fetch URL: https://github.com/my-org/complex-project Push URL: https://github.com/my-org/complex-project HEAD branch: master Remote branches: master tracked dev-branch tracked markdown-strip tracked issue-43 new (next fetch will store in remotes/origin) issue-45 new (next fetch will store in remotes/origin) refs/remotes/origin/issue-11 stale (use 'git remote prune' to remove) Local branches configured for 'git pull': dev-branch merges with remote dev-branch master merges with remote master Local refs configured for 'git push': dev-branch pushes to dev-branch (up to date) markdown-strip pushes to markdown-strip (up to date) master pushes to master (up to date)
This command shows which branch is automatically pushed to when you run git push while on certain branches. It also shows you which remote branches on the server you don’t yet have, which remote branches you have that have been removed from the server, and multiple local branches that are able to merge automatically with their remote-tracking branch when you run git pull.
Renaming and Removing Remotes
You can run git remote rename to change a remote’s shortname. For instance, if you want to rename pb to paul, you can do so with git remote rename:
$ git remote rename pb paul $ git remote origin paul
It’s worth mentioning that this changes all your remote-tracking branch names, too. What used to be referenced at pb/master is now at paul/master.
If you want to remove a remote for some reason — you’ve moved the server or are no longer using a particular mirror, or perhaps a contributor isn’t contributing anymore — you can either use git remote remove or git remote rm:
$ git remote remove paul $ git remote origin
Once you delete the reference to a remote this way, all remote-tracking branches and configuration settings associated with that remote are also deleted.
Git Commit 2 Parents
How can I tell what happened in a Git commit with two parents that did not merge in the changes from the second parent?
n Gitk I can see a team member's commit (X) that has two parents, the first parent is his own previous commit (A), the other parent contains lots of other people commits (1 through 5). After his merge all changes made by other people (1 through 5 and others) are no longer present at X, B, C, etc…
A------------
\
X - B - C
/
1--2--3--4--5
/
e--r--j--k
/
l--m
If I diff commit X to commit A it shows no differences, if I diff commit X to commit 5 it shows all the missing changes. Also, at commit X, B, or C git log does not show changes that were made to files in commits 1 through 5. However, if I do git log –full-history then history does show the changes that were made in 1 through 5, but those changes are not still present in the actual file and history does not show them being being undone. So git log –full-history seems to contradict the current file contents.
I talked to the user who made commit X. He says he did not do a reset or rebase and he says he hasn't reverted any commits during the time in question. However, he says that he does sometimes do a pull origin master that results in everyone else's changes getting put in his index or working tree as if he had made those changes and not the actual authors of those changes. He says when that happens he does a fresh clone and does not push anything from that local repo to master because he believes Git has done something wrong.
Are the two things related (bad pull and bad merge)?
How can I tell exactly what happened so that we can avoid this in the future?
And what causes Git to sometimes put changes pulled from origin master to be placed in the local working directory or index as if they were local changes?
gitgit-mergegit-commitgit-pullgit-log
Follow
asked Jan 22 '15 at 0:43
65755 silver badges1919 bronze badges
- A looks like it's hanging off in its own history. Do A and 1 have a common ancestor? – Schwern Jan 22 '15 at 1:17
- Yes, all branches have common ancestors, I just omitted that from my sketch. – DAC Jan 22 '15 at 1:23
2 Answers
12
However, he says that he does sometimes do a pull origin master that results in everyone else's changes getting put in his index or working tree as if he had made those changes and not the actual authors of those changes.
It sounds like he was getting merge conflicts but does not understand what they are. This is an extremely common problem, and unfortunately, we don't know a good way to avoid it (switching back to SVN doesn't avoid it, for example).
How could this happen, exactly?
Let's call your developers Alice and Bob. Alice made commits 1-5, and Bob made commits A and X. Here is a plausible history.
-
Bob makes commit A.
-
Alice makes commits 1-5, and pushes them to the central repository.
-
Bob tries to push A, but can't, because his repository is out of date.
$ git push ! [rejected] master -> master (non-fast-forward)
-
Bob then he does what you told him to do: he pulls first. However, he gets a merge conflict because commit A and commits 1-5 touch some of the same code.
$ git pull Auto-merging file.txt CONFLICT (content): Merge conflict in file.txt Automatic merge failed; fix conflicts and then commit the result.
-
Bob sees other people's changes in his working directory, and doesn't understand why the changes are there.
$ git status both modified: file.txt
-
He thinks Git is doing something wrong, when in fact, Git is asking him to resolve a merge conflict. He tries to check out a fresh copy, but gets an error:
$ git checkout HEAD file.txt error: path 'file.txt' is unmerged
-
Since it doesn't work, he tries
-f
:$ git checkout -f HEAD file.txt warning: path 'file.txt' is unmerged
-
Success! He commits and pushes.
$ git commit $ git push
The part where it gets harder
There are a lot of git tools out there. Seriously. Visual Studio and Xcode both come with Git integration, there are several other GUIs, and there are even multiple command-line clients. People are also sloppy with the way they describe how they use Git, and most developers are not quite comfortable enough with how Git works outside of the "pull commit push" workflow.
There was an excellent paper on this very subject not too long ago (I'm having a hard time finding it). Some of the conclusions were (forgive my memory):
- Most developers don't really know how to use source control, except for a few really simple commands (commit, push).
- When source control doesn't behave the way developers expect, they resort to tactics such as copy-pasting some command they don't quite understand to "fix things", adding the
-f
flag, or erasing the repository and starting again with a clean copy. - On development teams, it is often the case that only the lead developers really know what is going on in the repo.
So this is really an educational challenge.
I think the key lesson here that Bob needs to learn is that git pull
is really just git fetch
and git merge
, and that you can get merge conflicts, and you need to act in a very conscientious and purposeful manner when resolving merges. This applies even when there are no reported conflicts… but let's not blow Bob's mind too much for now!
The other key lesson here is that lead developers need to take the time to ensure that everyone on the team can use source control correctly, and understands how pulling, pushing, branching, and merging are all related. This is a great opportunity for a lunchtime lecture: put together some slides, buy pizza, and talk about how Git works.
-
2
I thought Bob knew how to resolve merge conflicts, however, since you suspect this, I'll investigate what Bob actually does when conflicts arise. Will comment again after doing so. – DAC Jan 22 '15 at 1:42
-
1
He probably does know how to resolve merge conflicts, but some people don't realize that you can get merge conflicts when you do a
git pull
, and some people will run increasingly reckless commands when Git is doing something that they don't understand. – Dietrich Epp Jan 22 '15 at 3:40 -
Further discussion resulted in the user recalling that maybe he did do a rebase followed by a push after all. He also said that when a pull results in other people's changes in his working tree he becomes convinced that Git has done something wrong and re clones, and he uses the IDE's conflict resolution GUI tool. – DAC Jan 23 '15 at 1:11
-
2
I have come to realize how this usually happens. When pull origin master fails due to conflicts a git status will show all of the changes from the other branch as staged to commit. Bob thinks, those aren't my changes, panics and starts unstaging stuff. But actually, Bob must commit all those other people's changes after resolving the conflicts, otherwise, git will never merge those in. Solution is tell Bob, when you have conflicts, resolve conflicts and commit. Don't worry about other peoples changes in your staged, that's normal. – DAC Apr 30 '18 at 20:52
-
5
Hello, I'm Bob. – Betlista Jan 12 '20 at 11:07
Revertin a merge commit (also a commit with 2 parents)
https://levelup.gitconnected.com/reverting-a-merge-commit-7de2e9114c7d
EVERTING A COMMIT
git revert
The revert command in git takes in a commit id and compares the changes with the parent. The delta or the diff is calculated and the negation of it applied as a new commit. In case the commit-sha is not specified, it is defaulted to the commit-sha of the HEAD commit.
Before Revert
$ git revert 9735432
This command creates a commit fbb1df5 on top of the HEAD negating the changes made by 9735432. The new HEAD will then point to the fbb1df5. The resultant tree will behave as if the commit 9735432 does not exist.
After Revert
THE MERGE COMMIT
Unlike other commits, the merge commit is a commit which has multiple (generally two) parents.
For instance, when a branch named feature is merged with master, a new commit is created on the branch master which has two parents, the previous head of master and the head of feature.
The branches before Merge
On merging the feature to master.
$ git checkout master
$ git merge feature
These commands create a new merge commit 1c32600.
The branches after merge
The merge commit 1c32600 has two parent commits
- 9735432 from master before the merge
- 1484b1a from branch feature
On running git show, the new commits display both the parents
$ git show
commit 1c32600da72208f8964da85fddb80e7dd43b15c9 (HEAD -> master)
Merge: 9735432 1484b1a
REVERTING THE MERGE COMMIT
While reverting the merge commit, the parent with which it needs to be compared should be specified. The parent may be specified with the -m flag in git revert followed by the parent-number.
The parent number is assigned from left. To revert the changes brought in by the feature branch, revert the commit with respect to the second parent (1484b1a).
$ git revert HEAD -m 1
This will revert all the changes made by the second branch (feature) on master. The resulting tree will behave as the branch feature was never merged to master.
git revert -m 2
Similarly, to revert the changes from the commits in the first parent of the merge commit run
$ git revert HEAD -m 1
This will revert all the commits that were made on the master after the feature branch was created leaving only the commits in the feature branch in the master.
git revert HEAD -m 1
In the above example,9745432 and b15b045 would be removed from the master branch leaving only the commits 1484b1a and 79fe70a and the older commits which are in feature.
Also, the master branch may be merged to feature branch.
$ git checkout feature
$ git merge master
Merge the master to feature branch
The changes in the commit in the 9745432 and b15b045 in the master branch will get included in the feature branch. This time for the merge commit the first parent is the original branch which is the commit 1484b1a itself whereas the commit in the master branch 9745432 is the second parent.
CAUTION
If the merge of master to the feature branch was unintentional. The correct way to undo it is to reset the branch. This can be done by running the following in the feature branch.
$ git reset HEAD~1
On the other hand, reverting a merge commit negates all the changes made by the branch of the specified parent.
For instance if after reverting the merge commit(177a8b) in the feature branch, it were merged back to master*,* it would wipe out the changes (9745432 and b15b045) made in the master branch.
Merging back after revert wipes out the changes
Now the master branch pointing to the commit a75ebc will not have the changes done in the commits 9745432 and b15b045.
Thanks for reading. Hope this was helpful. Please leave your comments if you have any questions or you feel something more needs to be added. Also do check out this blog Git Internals for a deeper explanation of how the git objects are structured under the hood.
The Problem
There are a number of work-flows you can use. The main point is not to break history in a published branch unless you've communicated with everyone who might consume the branch and are willing to do surgery on everyone's clones. It's best not to do that if you can avoid it.
Solutions for Published Branches
Your outlined steps have merit. If you need the dev branch to be stable right away, do it that way. You have a number of tools for Debugging with Git that will help you find the right branch point, and then you can revert all the commits between your last stable commit and HEAD.
Either revert commits one at a time, in reverse order, or use the <first_bad_commit>..<last_bad_commit>
range. Hashes are the simplest way to specify the commit range, but there are other notations. For example, if you've pushed 5 bad commits, you could revert them with:
# Revert a series using ancestor notation.
git revert --no-edit dev~5..dev
# Revert a series using commit hashes.
git revert --no-edit ffffffff..12345678
This will apply reversed patches to your working directory in sequence, working backwards towards your known-good commit. With the –no-edit flag, the changes to your working directory will be automatically committed after each reversed patch is applied.
See man 1 git-revert
for more options, and man 7 gitrevisions
for different ways to specify the commits to be reverted.
Alternatively, you can branch off your HEAD, fix things the way they need to be, and re-merge. Your build will be broken in the meantime, but this may make sense in some situations.
The Danger Zone
Of course, if you're absolutely sure that no one has pulled from the repository since your bad pushes, and if the remote is a bare repository, then you can do a non-fast-forward commit.
git reset --hard <last_good_commit>
git push --force
This will leave the reflog intact on your system and the upstream host, but your bad commits will disappear from the directly-accessible history and won't propagate on pulls. Your old changes will hang around until the repositories are pruned, but only Git ninjas will be able to see or recover the commits you made by mistake.
-
If people already cloned bad pushes, and were notified – what should they do to have the same branch as in the remote? Do they have to do the same
git reset --hard <last_good_commit>
? – andrybak Oct 21 '15 at 17:43 -
5
If you are using commit tags, it's not
<first_bad_commit>
..<last_bad_commit>
, but rather<last_good_commit>
..<last_bad_commit>
– Yerke Feb 10 '19 at 9:47
If you've already pushed things to a remote server (and you have other developers working off the same remote branch) the important thing to bear in mind is that you don't want to rewrite history
Don't use git reset –hard
You need to revert changes, otherwise any checkout that has the removed commits in its history will add them back to the remote repository the next time they push; and any other checkout will pull them in on the next pull thereafter.
If you have not pushed changes to a remote, you can use
git reset --hard <hash>
If you have pushed changes, but are sure nobody has pulled them you can use
git reset --hard
git push -f
If you have pushed changes, and someone has pulled them into their checkout you can still do it but the other team-member/checkout would need to collaborate:
(you) git reset --hard <hash>
(you) git push -f
(them) git fetch
(them) git reset --hard origin/branch
But generally speaking that's turning into a mess. So, reverting:
The commits to remove are the lastest
This is possibly the most common case, you've done something – you've pushed them out and then realized they shouldn't exist.
First you need to identify the commit to which you want to go back to, you can do that with:
git log
just look for the commit before your changes, and note the commit hash. you can limit the log to the most resent commits using the -n
flag: git log -n 5
Then reset your branch to the state you want your other developers to see:
git revert <hash of first borked commit>..HEAD
The final step is to create your own local branch reapplying your reverted changes:
git branch my-new-branch
git checkout my-new-branch
git revert <hash of each revert commit> .
Continue working in my-new-branch
until you're done, then merge it in to your main development branch.
The commits to remove are intermingled with other commits
If the commits you want to revert are not all together, it's probably easiest to revert them individually. Again using git log
find the commits you want to remove and then:
git revert <hash>
git revert <another hash>
..
Then, again, create your branch for continuing your work:
git branch my-new-branch
git checkout my-new-branch
git revert <hash of each revert commit> .
Then again, hack away and merge in when you're done.
You should end up with a commit history which looks like this on my-new-branch
2012-05-28 10:11 AD7six o [my-new-branch] Revert "Revert "another mistake""
2012-05-28 10:11 AD7six o Revert "Revert "committing a mistake""
2012-05-28 10:09 AD7six o [master] Revert "committing a mistake"
2012-05-28 10:09 AD7six o Revert "another mistake"
2012-05-28 10:08 AD7six o another mistake
2012-05-28 10:08 AD7six o committing a mistake
2012-05-28 10:05 Bob I XYZ nearly works
Better way®
Especially that now that you're aware of the dangers of several developers working in the same branch, consider using feature branches always for your work. All that means is working in a branch until something is finished, and only then merge it to your main branch. Also consider using tools such as git-flow to automate branch creation in a consistent way.
FETCH_HEAD
is a short-lived ref, to keep track of what has just been fetched from the remote repository. git pull
first invokes git fetch
, in normal cases fetching a branch from the remote; FETCH_HEAD
points to the tip of this branch (it stores the SHA1 of the commit, just as branches do). git pull
then invokes git merge
, merging FETCH_HEAD
into the current branch.
The result is exactly what you'd expect: the commit at the tip of the appropriate remote branch is merged into the commit at the tip of your current branch.
This is a bit like doing git fetch
without arguments (or git remote update
), updating all your remote branches, then running git merge origin/<branch>
, but using FETCH_HEAD
internally instead to refer to whatever single ref was fetched, instead of needing to name things.
This depends a lot on what you mean by "revert".
Temporarily switch to a different commit
If you want to temporarily go back to it, fool around, then come back to where you are, all you have to do is check out the desired commit:
# This will detach your HEAD, that is, leave you with no branch checked out:
git checkout 0d1d7fc32
Or if you want to make commits while you're there, go ahead and make a new branch while you're at it:
git checkout -b old-state 0d1d7fc32
To go back to where you were, just check out the branch you were on again. (If you've made changes, as always when switching branches, you'll have to deal with them as appropriate. You could reset to throw them away; you could stash, checkout, stash pop to take them with you; you could commit them to a branch there if you want a branch there.)
Hard delete unpublished commits
If, on the other hand, you want to really get rid of everything you've done since then, there are two possibilities. One, if you haven't published any of these commits, simply reset:
# This will destroy any local modifications.
# Don't do it if you have uncommitted work you want to keep.
git reset --hard 0d1d7fc32
# Alternatively, if there's work to keep:
git stash
git reset --hard 0d1d7fc32
git stash pop
# This saves the modifications, then reapplies that patch after resetting.
# You could get merge conflicts, if you've modified things which were
# changed since the commit you reset to.
If you mess up, you've already thrown away your local changes, but you can at least get back to where you were before by resetting again.
Undo published commits with new commits
On the other hand, if you've published the work, you probably don't want to reset the branch, since that's effectively rewriting history. In that case, you could indeed revert the commits. With Git, revert has a very specific meaning: create a commit with the reverse patch to cancel it out. This way you don't rewrite any history.
# This will create three separate revert commits:
git revert a867b4af 25eee4ca 0766c053
# It also takes ranges. This will revert the last two commits:
git revert HEAD~2..HEAD
#Similarly, you can revert a range of commits using commit hashes (non inclusive of first hash):
git revert 0d1d7fc..a867b4a
# Reverting a merge commit
git revert -m 1 <merge_commit_sha>
# To get just one, you could use `rebase -i` to squash them afterwards
# Or, you could do it manually (be sure to do this at top level of the repo)
# get your index and work tree into the desired state, without changing HEAD:
git checkout 0d1d7fc32 .
# Then commit. Be sure and write a good message describing what you just did
git commit
The git-revert
manpage actually covers a lot of this in its description. Another useful link is this git-scm.com section discussing git-revert.
If you decide you didn't want to revert after all, you can revert the revert (as described here) or reset back to before the revert (see the previous section).
You may also find this answer helpful in this case:
How can I move HEAD back to a previous location? (Detached head) & Undo commits
-
155
@Rod's comment on
git revert HEAD~3
as the best wat to revert back3
commits is am important convention. – New Alexandria Aug 22 '12 at 15:16 -
27
Could you write the whole number? like:
git reset --hard 0d1d7fc32e5a947fbd92ee598033d85bfc445a50
– Spoeken Dec 4 '12 at 13:58 -
19
@MathiasMadsenStav Yes, you can of course specify commits by the full SHA1. I used abbreviated hashes to make the answer more readable, and you also tend to use them if you're typing out. If you're copying and pasting, by all means use the full hash. See Specifying Revisions in man git rev-parse for a full description of how you can name commits. – Cascabel Dec 4 '12 at 16:55
-
64
You can use
git revert --no-commit hash2 hash2 ...
and after this just commit every single revert in one commitgit commit -m "Message"
– Mirko Akov Sep 24 '13 at 12:12
Finding Merge Commits
p>https://stackoverflow.com/questions/3824050/telling-if-a-git-commit-is-a-merge-revert-commit
Figuring out if something is a merge is easy. That's all commits with more than one parent. To check for that, you can do, for example
$ git cat-file -p $commit_id
If there's more than one `parent' line in the output, you found a merge.
For reverts it's not as easy. Generally reverts are just normal commits that happen to apply the diff of a previous commit in reverse, effectively removing the changes that commit introduced. There're not special otherwise.
If a revert was created with git revert $commit
, then git usually generates a commit message indication the revert and what commit it reverted. However, it's quite possible to do reverts in other ways, or to just change the commit message of a commit generated by git revert
.
Looking for those generated revert commit message might already be a good enough heuristic for what you're trying to achieve. If not, you'd have to actually look through other commits, comparing their diffs against each other, looking of one is the exact reverse operation of another. But even that isn't a good solution. Often enough reverts are slightly different than just the reverse of the commit they're reverting, for example to accomodate for code changes that happened between the commit and the revert.
Identify the hash of the commit, using git log, then use git revert
git push origin amd_qlp_tester will work for you. If you just type git push, then the remote of the current branch is the default value.
Syntax of push looks like this – git push
[core] repositoryformatversion = 0 filemode = true bare = false logallrefupdates = true ignorecase = true precomposeunicode = true [remote "origin"] url = https://git.quantox.tech/Ciric/ns-forge-site.git fetch = +refs/heads/*:refs/remotes/origin/* [branch "stage"] remote = origin merge = refs/heads/stage [branch "Trenton-Stage-Mrg2Aug9"] remote = origin merge = refs/heads/trenton-ducatti
Previous versions
[core] repositoryformatversion = 0 filemode = true bare = false logallrefupdates = true ignorecase = true precomposeunicode = true [remote "origin"] url = https://git.quantox.tech/Ciric/ns-forge-site.git fetch = +refs/heads/*:refs/remotes/origin/* [branch "trentonsmpAug3"] remote = origin merge = refs/heads/trenton-ducatti
Branches
* Trenton-Stage-Mrg2Aug9 smpAug11StageTrenton stage remotes/origin/HEAD -> origin/ns-site-setup remotes/origin/guerilla-porn remotes/origin/ns-site-setup remotes/origin/smp-trenton-ducatti remotes/origin/stage remotes/origin/trenton-ducatti
https://stackoverflow.com/questions/17756753/where-do-the-settings-in-my-git-configuration-come-from
Git checks four places for a configuration file:
- Your machine's system
.gitconfig
file. - Your user
.gitconfig
file located at~/.gitconfig
. - A second user-specific configuration file located at
$XDG_CONFIG_HOME/git/config
or$HOME/.config/git/config
. - The local repository's configuration file
.git/config
.
The settings cascade in the following order, with each file adding or overriding settings defined in the file above it.
- System configuration.
- User configuration.
- Repository-specific configuration.
You can see what each file has defined using the following commands:
# System, applies to entire machine and all users
$ git config --system --list
$ git config --system --edit
# User defined
$ git config --global --list
$ git config --global --edit
You can see what just the repository-specific file has defined by opening up the file .git/config
for that repository.
If you're using MSysGit on Windows, you'll probably find your user ~/.gitconfig
file where ever %homepath%
points to if you use echo %homepath%
from a Windows command prompt.
From the documentation for git config
:
If not set explicitly with
--file
, there are four files wheregit config
will search for configuration options:
$(prefix)/etc/gitconfig
System-wide configuration file.
$XDG_CONFIG_HOME/git/config
Second user-specific configuration file. If
$XDG_CONFIG_HOME
is not set or empty,$HOME/.config/git/config
will be used. Any single-valued variable set in this file will be overwritten by whatever is in~/.gitconfig
. It is a good idea not to create this file if you sometimes use older versions of Git, as support for this file was added fairly recently.
~/.gitconfig
User-specific configuration file. Also called "global" configuration file.
$GIT_DIR/config
Repository specific configuration file.
If no further options are given, all reading options will read all of these files that are available. If the global or the system-wide configuration file are not available they will be ignored. If the repository configuration file is not available or readable,
git config
will exit with a non-zero error code. However, in neither case will an error message be issued.The files are read in the order given above, with last value found taking precedence over values read earlier. When multiple values are taken then all values of a key from all files will be used.
All writing options will per default write to the repository specific configuration file. Note that this also affects options like
--replace-all
and--unset
.git config
will only ever change one file at a time.You can override these rules either by command-line options or by environment variables. The
--global
and the--system
options will limit the file used to the global or system-wide file respectively. TheGIT_CONFIG
environment variable has a similar effect, but you can specify any filename you want.
Parent Number
https://stackoverflow.com/questions/7099833/how-to-revert-a-merge-commit-thats-already-pushed-to-remote-branch?lq=1
The -m option specifies the parent number. This is because a merge commit has more than one parent, and Git does not know automatically which parent was the mainline, and which parent was the branch you want to un-merge.
When you view a merge commit in the output of git log, you will see its parents listed on the line that begins with Merge:
commit 8f937c683929b08379097828c8a04350b9b8e183
Merge: 8989ee0 7c6b236
Author: Ben James
Date: Wed Aug 17 22:49:41 2011 +0100
Merge branch ‘gh-pages’
Conflicts:
README
In this situation, git revert 8f937c6 -m 1 will get you the tree as it was in 8989ee0,
and git revert -m 2 will reinstate the tree as it was in 7c6b236.
To better understand the parent IDs, you can run:
git log 8989ee0
and
git log 7c6b236
https://stackoverflow.com/questions/56521974/why-did-this-revert-fail
https://stackoverflow.com/questions/56521974/why-did-this-revert-fail
A typical merge commit would be shown as below in the git log
command output.
commit dddfd0b6d529bfcdcd6515555ea1dcf186fe338
Merge: 6b5619b 40ad694
Author: Raja Anbazhagan <raja.anbazhagan@example.com>
Date: Fri Jun 7 03:11:23 2019 +0530
Merge branch 'xyz' into 'develop'
Here, You can see that the second line contains two short hashes. 6b5619b
and 40ad694
. Both of these are the top most commits of the branches that got merged.
Here 6b5619b
is the top most commit id of the branch develop
. And 40ad694
is the top most commit of the feature branch xyz
.
I am telling you all this is because this information is important for what I am going to explain next.
When you are resetting or reverting a commit, it will try to figure out what had changed in that commit by comparing it to its ancestor commit.
In this case there are two ancestors 6b5619b
and 40ad694
and GIT is now not sure from which ancestor it has to find the diff.
In these cases, the user will have to provide the appropriate parent commit id for the process to continue. Which is done with a flag -m followed by an ordinal number that represents where the parent commit id resides in the merge commit.
for my sample merge commit, possible -m values are 1 and 2. 1 for 6b5619b
and 2 for 40ad694
.
So if you want to revert your code on your develop branch, you should do
git revert -m 1 <merge-commit>
With -m 1
the git revert happens in relevance to develop branch (first parent of the merge). Passing -m 2
would result in the revert happening in relevance to the feature branch xxx
In general cases -m 1
is the one you should use. But that is not true for all cases.
GIT: PUSHING TO A REMOTE BRANCH WITH A DIFFERENT NAME
Normally when I do a push in git I do something like git push origin master, which really means push from the local branch named master to the remote branch named master. If you want to push to a remote branch with a different name than your local branch, separate the local and remote names with a colon:
git push origin local-name:remote-name git push --dry-run origin Trenton-Stage-Mrg2Aug9:trenton-ducatti git push origin Trenton-Stage-Mrg2Aug9:trenton-ducatti
https://www.toolsqa.com/git/git-push/
git push --dry-run <remote> <local_branch>
Throughout this whole course, we have had a detailed discussion of connecting the local repository with the remote repository and cloning a repository to the local machine. The content of this post is quite apparent. It is the next milestone in the series and information on the process of reflecting the changes that the user has done on the local system onto the GitHub account/remote repositories. Yes, we are going to learn about Git Push.
In this article, we are going to cover:-
-
What is Git Push Command?
-
How to Push Changes from Local Repository to Remote Repository in Git?
-
Options Available in Git Push command in Git
- Prune Option in Git Push
- Dry Ryn in Git Push
- Atomic in Git Push
- All in Git Push
Before starting the tutorial, we will request the user to learn the things given below.
Pre-Requisites for Pushing Changes in Git:
- How to connect Git Local Repository with the remote repository (Refer [Link*](https://www.toolsqa.com/git/local-repository-remote-repository/)).*
- How to fork a repository to the GitHub account (Refer [Link*](https://www.toolsqa.com/git/git-fork/)).*
- Procedure to clone a repository to the local machine (Refer [Link*](https://www.toolsqa.com/git/git-clone/)).*
What is Git Push Command?
A git push command, when executed, pushes the changes that the user has made on the local machine to the remote repository. Once the users have cloned the remote repository and have made the necessary changes in their local device, these changes need to be pushed to the remote repository. The reason being, so that they are shared and used by other users. Git push command does it. These changes represent commitments performed on the repository and not the uncommitted changes (if any).
In addition to this, the changes that the user makes to the local system are of no worth to the contributors and viewers if the GitHub cloud does not reflect it. Imagine a user working on modifying some software (third-party repository), and merging the changes done is not easy. For instance, if you are working in a team on a single project, all the team members can push their code changes to the Github remote repository. Additionally, other members can fork and pull the changes from that remote repository. Therefore, it becomes effortless for multiple users to share their code change with all the team members.
To be able to push to your remote repository, you must ascertain that all your changes to the local repository are committed.
Consider Git push as a part of the synchronization process in Git. The synchronization happens between the local and remote repository where the source and the receiver may vary. There are a lot of other parts to sync and git push is one of the parts because it uploads the changes done on the local repository to keep the remote repository up to date. There is nothing complicated about it, and the concept is simple, just like its syntax.
The above image suffices the concept in a nutshell.
- The user clones a repository as a first step to make some changes in the repository.
- Thereafter, they proceed to make the changes to the local system and add these changes to the staging area.
- Upon finalizing all the changes, the user then commits all the changes to the local repository.
- After their satisfaction, they push these changes to the remote server. Finally, it synchronizes the local and remote repository.
Syntax of Git Push command in Git:
Execution of Git push command happens by typing the following command:
git push <remote_repo> <branch_name>
- remote_repo: This is the name (or alias) of the remote repository to which we are pushing the changes.
- branch_name: This is the branch the user is pushing to the remote repository.
We will talk about branches in the Branches in the GitHub tutorial. But till then imagine that a branch in Git is similar to the branches in a tree. Every branch represents a new feature or modification under development. Additionally, the main branch is the stable code like the trunk of the tree, also called a master branch. Which, in turn, helps the unstable code of branches to stay away from the stable main code.
In the next section, we will see how to push the changes to the remote cloud repository.
How to Push Changes from Local Repository to Remote Repository in Git
To push some changes to the remote repository, the repository must, first of all, contain some commits on the local system. Therefore, in this section, we will first create some changes to the repository. Secondly, we will commit those changes, and finally, we will reflect them in the remote repository.
Before creating the changes onto the repository, ensure that you have performed the following operations:
- You have forked a repository to the GitHub account.
- You have cloned the same repository to the local machine.
Note: In this tutorial, we will use the ToolsQA repository that has already been forked and cloned in the previous tutorials. The user is free to use any public repository. However, the recommendation is to use the same repository for this tutorial is recommended.
As a good practice first, check that you have a clean repository through git status command (no pending changes to commit).
The following lines appear after executing the git status command:
On branch master: Denotes that we are currently on the master branch. Since there are no other branches yet, we are on the master branch by default.
Your branch is up to date with origin/master: Origin is the name of the remote repository that we gave while connecting the local repository with the remote repository. Please refer to this [link*](https://www.toolsqa.com/git/local-repository-remote-repository/) to know more.*
- List all the files with the ls command in the repository.
Since there is only one file (README.md is just instructions), let's make some changes to its content.
- Open the file using your favorite editor and make any changes to the file.
- We have changed the file to the following code.
Note: This is a screenshot of the vi editor. You can use any editor of your choice.
- Add the changes made to the staging area and commit these changes.
Note: GitHub and Git will recognize any change through commits only. If the user has not committed the changes and tries to push the changes to GitHub, it will display "Everything is up-to-date" message.
- Type the following command to push these changes into your GitHub repository and press enter.
git push origin master
Note: Please refer to the syntax section above to know about the syntax of this command.
- The user gets a prompt to provide the credentials by GitHub as a part of security. Provide your credentials and tap on the Login button.
- Once the user gets the approval and the changes merge, the user will get the following message in Git Bash.
Note: The last two lines are as follows:
https://github.com/harishrajora805/ToolsQA.git: The repository URL which reflects the changes.
1b4522a..285f559: This depicts the hash value of both branches. So, the hash value of the final commit reflected on GitHub is 285f559.
master -> master: The line master-> master shows the source branch from which merging happens to the destination branch. In the above scenario, both are master branches.
The line above the highlighted line written as Writing Objects: 100% is essential. In Git, one can tell, whether the push command has executed successfully or not, only by looking at this line. If it shows 100%, then all the changes have been successfully pushed onto the cloud.
Along with the simple, straightforward command we discussed above, like any other command in Git, we can use options while executing the command to achieve a specific task. For example, if you want to push all the branches, you would use all option and so on. Let's see some of the options in Git.
Options Available in Git Push command in Git
As mentioned in the last section, there are many options available in the Git push command that helps us achieve certain specific tasks with just one execution. In this section, we will take you through the essential and most used options in the git push command.
Prune Option in Git Push
–prune option in git push command will delete branch XYZ from the remote repository if there does not exist any branch with the same name in the local repository.
Usage: git push --prune remote XYZ
Dry Run Option in Git Push
This option will perform and show the execution of the git push command but will not send any updated to the remote repository.
Usage: git push --dry-run <remote> <local_branch>
Atomic Option in Git Push
Atomic option in Git Push provides an atomic operation on the remote repository, i.e., either every reference update or nothing at all.
git push --atomic <remote_repo> <working_branch>
All Option in Git Push
All options will push all the branches and their committed changes to the remote repository.
Usage: git push --all <remote>
By this, a Successful push operation completes. Don't relax just now; the job does not finish here. It is not just enough to push the changes to GitHub. The verification of these changes onto the account should happen. In addition to this, an analysis happens which tells how these changes get reflected. Let's analyze the difference and see if they update or not, in the next tutorial.