#include <bits/stdc++.h>
using namespace std;
struct BASIC {
  int base[31];
  void insert(int w) {
    for (int i = 30, j; i >= 0; i--)
      if (w & (1 << i)) {
        if (!base[i]) {
          for (base[i] = w, j = 30; j > i; j--)
            if (base[j] & (1 << i)) base[j] ^= w;
          break;
        } else
          w ^= base[i];
      }
  }
  int query(int x) {
    for (int i = 30; i >= 0; i--)
      if ((x ^ base[i]) < x) x ^= base[i];
    return x;
  }
} V[30];
int fa[200010], dis[200010], size[200010];
int find(int x) { return x == fa[x] ? x : find(fa[x]); }
int GetDis(int x) {
  int res = 0;
  while (x != fa[x]) res ^= dis[x], x = fa[x];
  return res;
}
void nunion(int x, int y, int w, vector<int> &d) {
  int tmp1 = GetDis(x), tmp2 = GetDis(y);
  x = find(x), y = find(y);
  if (size[x] > size[y]) swap(x, y);
  dis[x] = w ^ tmp1 ^ tmp2, fa[x] = y, size[y] += size[x], d.push_back(x);
}
void Clear(vector<int> &d) {
  for (int i = 0; i < d.size(); i++) fa[d[i]] = d[i], dis[d[i]] = 0;
  d.clear();
}
struct Edge {
  int fm, to, st, ed, w;
};
struct Ask {
  int u, v, id;
};
vector<Ask> q[200010];
int ans[200010], flg[200010];
void CDQ(int l, int r, int dep, vector<Edge> &e) {
  for (int i = 0; i <= 30; i++) V[dep].base[i] = V[dep - 1].base[i];
  vector<int> d;
  vector<Edge> L, R;
  int mid = (l + r) >> 1;
  for (int i = 0; i < e.size(); i++) {
    if (e[i].st <= l && e[i].ed >= r) {
      if (find(e[i].fm) == find(e[i].to))
        V[dep].insert(GetDis(e[i].fm) ^ GetDis(e[i].to) ^ e[i].w);
      else
        nunion(e[i].fm, e[i].to, e[i].w, d);
      continue;
    }
    if (e[i].st <= mid) L.push_back(e[i]);
    if (e[i].ed > mid) R.push_back(e[i]);
  }
  if (l == r) {
    for (int i = 0; i < q[l].size(); i++) {
      int u = q[l][i].u, v = q[l][i].v;
      if (find(u) != find(v)) continue;
      ans[q[l][i].id] = V[dep].query(GetDis(u) ^ GetDis(v));
    }
    Clear(d);
    return;
  }
  CDQ(l, mid, dep + 1, L), CDQ(mid + 1, r, dep + 1, R), Clear(d);
}
map<pair<int, int>, int> s;
int main() {
  int n, m;
  scanf("%d%d", &n, &m);
  vector<Edge> e;
  for (int i = 1, a, b, c; i <= m; i++) {
    scanf("%d%d%d", &a, &b, &c);
    if (a > b) swap(a, b);
    s[pair<int, int>(a, b)] = i, e.push_back((Edge){a, b, 0, (int)1e9, c});
  }
  for (int i = 1; i <= n; i++) fa[i] = i, size[i] = 1;
  int Q, cnt = m, t = 0;
  scanf("%d", &Q);
  for (int i = 1, a, b, c, d; i <= Q; i++) {
    scanf("%d%d%d", &a, &b, &c);
    if (a == 1)
      cnt++, t++, scanf("%d", &d), e.push_back((Edge){b, c, t, (int)1e9, d}),
          s[pair<int, int>(b, c)] = cnt;
    if (a == 2) {
      if (b > c) swap(b, c);
      t++, e[s[pair<int, int>(b, c)] - 1].ed = t - 1;
    }
    if (a == 3) q[t].push_back((Ask){b, c, i}), flg[i] = 1;
  }
  CDQ(0, t, 1, e);
  for (int i = 1; i <= Q; i++)
    if (flg[i]) printf("%d\n", ans[i]);
  return 0;
}
