How to manage git merge with essentially two masters? - linux

we have the following situation:
At time point t0, we took snapshot of C++ project in Unix, which was not finished (release 1702 under Unix), and worked on it migrating to Linux. This was established as Master in a new GIT server.
At time point t1, I created a new branch from Master called 1702, and overwrote everything with the up to date Unix code.
During t1, I made another branch linux_not_working, which is a clone of Master branch.
Now, I tried to merge 1702 into linux_not_working, with git mergetool for handling conflicts, and the result is bad: for example I modified all of the project's Makefiles to work in Linux, and the merge did not even display conflicts, just replaced them with the old Unix ones from 1702 branch, also I did not find how to tell vimdiff to take ALL from REMOTE and not LOCAL (as I understand it, BASE has no meaning in this particular merge).
How best to perform this merge, when in a sense, I have two Masters going? I need to take any new additions from 1702, while KEEPING my customizations in linux_not working (manually, but its a lot of files so cherry pick is not ideal).
Any suggestions for the future? They are going to have to do it at least once more, while a contractor is working on 1703 release, and only later production development will shift to Linux.
Essentially, what I want to do is for GIT to tell me for each file: "File R and L are different, which one you want to keep? (allowing me to take different parts of each, IF it happened to have been modified by both branches)"
Thanks!

Essentially, what I want to do is for GIT to tell me for each file: "File R and L are different, which one you want to keep? (allowing me to take different parts of each, IF it happened to have been modified by both branches)"
If you don't need 3-way merge, you can simply check out the content of the branch and review the change with git gui.
$ git checkout -b manual-merge linux_not_working
$ git checkout 1702 . # overwrites source with 1702's one
$ git gui # take or leave each diff
$ git commi
(Or you may want to do it backwards.)
$ git checkout -b manual-merge-2 1702
$ git checkout linux_not_working .
$ git gui
$ git commit
Once you have manually-merged result, you can overwrite and commit as a merge.
$ git checkout 1702
$ git merge linux_not_working
$ git reset
$ git checkout manual-merge . # or manual-merge-2
$ git commit

Related

Closing a mercurial branch creates a new head?

I'm trying to close an old branch that is no longer used but every time I do the close command on this branch it says a new head is created. Other branches do not have this issue. Does anyone know what my issue could be?
jchan#jchan-Z170N:~/eclipse-workspace/filtec-src/src$ hg --version
Mercurial Distributed SCM (version 3.7.3)
...
jchan#jchan-Z170N:~/eclipse-workspace/filtec-src/src$ hg update -r version1.5.11 -C
1367 files updated, 0 files merged, 6050 files removed, 0 files unresolved
jchan#jchan-Z170N:~/eclipse-workspace/filtec-src/src$ hg commit --close-branch -m "closing legacy branch"
created new head
when i query the list of branches again this branch keeps showing up:
hg branches
...
version1.5.11
Why is this? I am using mercurial command line on Ubuntu 16.04.
Found that I was able to use the tortoise Hg tool "thg" to search and find all the head commits on the miss behaving branch and then merge them all together. After merging all these similar heads together I was able to close the final head and now this branch no longer comes up in the hg branches query.

The "git fetch" does nothing on repo

I noticed with git log origin/master that new a commit is up.
So I want to "see" this commit on my local repo.
I do this
$ git fetch -v
From xxx.xxx:proj/test
= [up to date] master -> origin/master
Everything seems fine... But nothing has changed on my local repo !?
To update your branches (as opposed to your Git's memory of some other Git's branches—git fetch updates this memory only), you must run a second Git command.
The second command to run is sometimes git merge and sometimes git rebase, depending on how you prefer to work. If you have no preference yet, use either one until you do have a preference.
There is a convenience command spelled git pull, that runs both git fetch and then the second command. The second command it runs is the one you tell it to. You must configure it based on your choice of second command to use. I recommend avoiding this until you really understand what the second command is and does, because eventually something will go wrong when running the second command. If you do not know that git pull is running this second command, you will not only not know what to do about this failure ... you won't even know that you need to look for how to fix problems with the other command!

move local repo to remote single file [duplicate]

This question already has answers here:
How do I move my local Git repository to a remote Git repository
(9 answers)
Closed 6 years ago.
I apologize if this has been asked somewhere else and I missed it. I've found many questions and answers that are close to what I'm trying to do, but none that fit exactly.
I have local files and projects in a local git repository. I created the repository a few months back as a way to safeguard and track my own work. The rest of our company uses SVN so I am the first to use git here. I set it up in my home directory on a Linux server. This repo contains many commits, branches, and tags that span my work over the past few months.
I want to move that repo to a more accessible location within our company's Linux server (not in my home directory) so others can clone and work with the entire repo (including all the tags, branches, history, etc.) as they see fit.
I've thought about copying or moving the entire file structure, but I want it to be a single file - i.e. myRepo.git.
How do I do this so that myRepo.git contains all the information I've committed such that when someone clones this repo and runs 'gitk --all', they will see all the branches, tags, etc.?
Thanks for your help.
You can git clone --bare your repo from somewhere other people can access it.
The most basic remote Git repo is nothing but a bare clone. A bare clone means it doesn't have a checkout, it's just the contents of the .git directory. Having a checkout would mean people might try to use that checkout as their own git working directory and make changes and that would get confusing with other people pushing changes to the repository.
For example, I'll make a new repository in foo/ and commit a file.
$ git init foo
Reinitialized existing Git repository in /Users/schwern/tmp/foo/.git/
$ rm -rf foo
$ git init foo
Initialized empty Git repository in /Users/schwern/tmp/foo/.git/
$ cd foo
$ touch this
$ git add this
$ git ci -m 'First commit'
[master (root-commit) 1a0bddf] First commit
1 file changed, 0 insertions(+), 0 deletions(-)
create mode 100644 this
Then I'll make a bare clone of it into bar/ (cloning doesn't have to happen over a network).
$ git clone --bare foo bar
$ ls
HEAD config description hooks info objects packed-refs refs
Instead of the checkout, it has the contents of the .git directory.
Now I can clone from that.
$ git clone bar baz
Cloning into 'baz'...
done.
$ cd baz/
$ git log
commit 1a0bddf415f48d71fa3aacc79c07c233d91ed4a9 (HEAD -> master, origin/master, origin/HEAD)
Author: Michael G. Schwern <schwern#pobox.com>
Date: Tue Feb 14 12:01:13 2017 -0800
First commit
That's cloning on a local filesystem. Git will, of course, clone over a network. Typically it uses ssh or https. git clone user#host/path is really sshing into host as user and copying what's in path.
So you can put your repo anywhere the other folks have ssh access, like a dev server, or the same host that has the SVN server.
That's the most bare bones way to share your Git repository. There are plenty of more sophisticated Git servers out there that provide web access and more protocols. Everything from the very sparse GitWeb to Gitlab, a Github clone you can host locally for free.
You can read more about this in Pro Git's chapter on Git Servers.
A fully functional git repo is not a single file, and there is no way to make it so. That said, copying your working repo isn't the best thing to do either.
If having a single file is more important that having the repo be fully functional - i.e. you don't care if your coworkers can push to it - then you can create a bundle file.
git bundle create /path/to/my/repo.bundle --all
Your coworkers can clone from this, add it as a remote, pull or fetch from it... but they can't push to it (and neither can you; to add to it you'd have to recreate it).
A shared repo to be cloned from should normally be a bare repo. This is roughly equivalent to a copy of the .git directory from your working repo. If your existing repo is at /path/to/my/repo, you can create a suitable bare repo at /path/to/shared/repo by saying
cd /path/to/shared
git clone --mirror /path/to/my/repo
Note that I used --mirror instead of --bare; this has to do with how refs are copied and will work better if you intend this to be treated as the origin henceforth.
And yet at this point /path/to/my/repo is still considered the upstream. To fix that
cd /path/to/shared/repo
git remote remove origin
cd /path/to/my/repo
git remote add origin /path/to/shared/repo

What git operation ports my changes from kernel 3.14.y to 3.15.y?

I am using the Linux kernel in an embedded project. When I started, I used git to clone from kernel.org what was then the current stable release, 3.14.2. As new 3.14 kernels were released, I was able to upgrade to them by using git rebase . For example, I upgraded to 3.14.10 by using
git checkout linux-3.14.y
git pull
git checkout myproject
git rebase v3.14.10
However, if I try to upgrade to the 3.15 series by using
git checkout linux-3.15.y
git pull
git checkout myproject
git rebase v3.15.3
or
git merge v3.15.3
I get git merge conflicts on files that I have never touched.
Is there a recommended way to upgrade from 3.14.10 to 3.15.3?
Here is what is happening. Let's say the starting commit graph looks something like this:
-------------------------------------- myproject
/
/
-----------/---------------------------------o------ linux-3.14.y
/ C v3.14.10
/ B
----/---------------------------\-------------------------- master
A \
\
--------------------o--- linux-3.15.y
v3.15.3
I don't know that it exactly looks like this, but it illustrates the issue.
When rebasing, git searches back in history for the first commit that is part of both the current branch and the "upstream" branch specified. It collects all these commits for the rebase operation.
When the "upstream" specified is the one from which the current branch was originally created, the collected commits include only my own commits on the current branch, so there are no conflicts.
When the "upstream" specified is not the one from which the current branch was originally created, which is the case for the "git rebase v3.15.3", the collected commits include ones that are not my own commits. In the example, the point of convergence is commit A, and the rebase operation would include everything from point A to myproject. The ones between point A and point C are probably inappropriate for the desired operation.
Instead, what is needed is to continue to use linux-3.14.y as the "upstream" branch for the purpose of identifying which commits to rebase, but to specify a separate commit onto which to rebase these commits. That is what the "--onto" switch is for. So the required operation to port myproject to the v3.15.y kernel is
git checkout myproject
git rebase linux-3.14.y --onto v3.15.3

How can I remove last two commits in git and get my commit 1 as changes in working directory?

Here is the scenario:
On a smallish Ubuntu web server I have a git server running. The website is checked out from git repository. I had a bulk of changes that I added and committed. Git diff showed 50+ code files updated and 20000+ image files. I did not paid much attention to this thinking these should be ignored, my fault. A bit stupid but I thought it was quickest to just commit all changes as a bulk. Let's call it commit A
# Commit A
git add .
git commit -m "Changes so far in this year"
I discovered that I forgot to exclude working/output files (huge number of generated images). Other than these files (around 20000) I had about 50+ files with code changes.
After reading online and git manual I understood that best bet was to update .gitignore and generate a list of files to remove and remove cached. This should remove from commit but not the local folder. Let this be commit B
# Commit B
vi .gitignore
git ls-files -ci --exclude-standard -z | xargs -0 git rm --cached
git add .
git commit -m "Cleanup of generated files from commit history"
Trouble is that now my git push fails with following error
git push origin master
Counting objects: 19219, done.
error: pack-objects died of signal 9
error: pack-objects died with strange error
error: child process died of signal 9
error: died of signal 9
error: failed to push some refs to '/srv/gitrepositories/xxxx.git'
Answers on this question about error 9 suggests it might be due to git running out of memory.
My options?
Is commit A & commit B made up of huge
number of objects, which looking at the count above it seems?
Is there a better way to clean this mess up with possible option to remove commit A & commit B altogether from history and get my changes intact?
Idealy I want to go back to stage where my git diff reports only the 50+ code files. Images are now ignored by .gitignore
Can I delete a git commit but keep the changes? Is this what it sounds like? Can I do it twice for both commit A and commit B?
Yes, you can use git reset HEAD~2 to clear the last 2 commit from history permanently while keeping the changes in the working directory, then git push -f to force push your changed history to the remote.
If your repo is shared with others it's not advisable to change your commit history.

Resources